mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.1.5 MultiMap
This commit is contained in:
parent
0e5434fb5f
commit
af5b9e99b1
@ -2,6 +2,10 @@ compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
platforms:
|
||||
- uno
|
||||
- leonardo
|
||||
- due
|
||||
- zero
|
||||
# - due
|
||||
# - zero
|
||||
# - leonardo
|
||||
- m4
|
||||
- esp32
|
||||
# - esp8266
|
||||
# - mega2560
|
||||
|
@ -4,10 +4,14 @@ name: Arduino CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
arduino_ci:
|
||||
runTest:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Arduino-CI/action@master
|
||||
# Arduino-CI/action@v0.1.1
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 2.6
|
||||
- run: |
|
||||
gem install arduino_ci
|
||||
arduino_ci.rb
|
||||
|
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2011-2021 Rob Tillaart
|
||||
Copyright (c) 2011-2022 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// FILE: MultiMap.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.4
|
||||
// VERSION: 0.1.5
|
||||
// DATE: 2011-01-26
|
||||
// PURPOSE: Arduino library for fast non-linear mapping or interpolation of values
|
||||
// URL: https://github.com/RobTillaart/MultiMap
|
||||
@ -10,37 +10,39 @@
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.0.1 2011-01-26 initial version (see forum)
|
||||
// .....
|
||||
// ..... eons passed ...
|
||||
// 0.1.0 2015-03-29
|
||||
// 0.1.1 2020-04-09
|
||||
// 0.1.2 2020-06-19 fix library.json
|
||||
// 0.1.3 2021-01-02 add arduino-CI
|
||||
// 0.1.4 2021-05-27 fix arduino-lint
|
||||
// 0.1.3 2021-01-02 add Arduino-CI
|
||||
// 0.1.4 2021-05-27 fix Arduino-lint
|
||||
// 0.1.5 2021-12-22 update library.json, readme, license, minor edits
|
||||
|
||||
|
||||
#define MULTIMAP_LIB_VERSION (F("0.1.4"))
|
||||
#define MULTIMAP_LIB_VERSION (F("0.1.5"))
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
|
||||
// note: the in array should have increasing values
|
||||
template<typename T>
|
||||
T multiMap(T val, T* _in, T* _out, uint8_t size)
|
||||
T multiMap(T value, T* _in, T* _out, uint8_t size)
|
||||
{
|
||||
// take care the value is within range
|
||||
// val = constrain(val, _in[0], _in[size-1]);
|
||||
if (val <= _in[0]) return _out[0];
|
||||
if (val >= _in[size-1]) return _out[size-1];
|
||||
// value = constrain(value, _in[0], _in[size-1]);
|
||||
if (value <= _in[0]) return _out[0];
|
||||
if (value >= _in[size-1]) return _out[size-1];
|
||||
|
||||
// search right interval
|
||||
uint8_t pos = 1; // _in[0] allready tested
|
||||
while(val > _in[pos]) pos++;
|
||||
uint8_t pos = 1; // _in[0] already tested
|
||||
while(value > _in[pos]) pos++;
|
||||
|
||||
// this will handle all exact "points" in the _in array
|
||||
if (val == _in[pos]) return _out[pos];
|
||||
if (value == _in[pos]) return _out[pos];
|
||||
|
||||
// interpolate in the right segment for the rest
|
||||
return (val - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
|
||||
return (value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
|
||||
}
|
||||
|
||||
|
||||
@ -50,24 +52,24 @@ T multiMap(T val, T* _in, T* _out, uint8_t size)
|
||||
// note: the in array should have increasing values
|
||||
|
||||
template<typename T>
|
||||
T multiMap(T val, T* _in, T* _out, uint8_t size)
|
||||
T multiMap(T value, T* _in, T* _out, uint8_t size)
|
||||
{
|
||||
static T lastvalue = -1;
|
||||
static T cache = -1;
|
||||
|
||||
if (val == lastvalue)
|
||||
if (value == lastvalue)
|
||||
{
|
||||
return cache;
|
||||
}
|
||||
lastvalue = val;
|
||||
lastvalue = value;
|
||||
|
||||
// take care the value is within range
|
||||
// val = constrain(val, _in[0], _in[size-1]);
|
||||
if (val <= _in[0])
|
||||
// value = constrain(value, _in[0], _in[size-1]);
|
||||
if (value <= _in[0])
|
||||
{
|
||||
cache = _out[0];
|
||||
}
|
||||
else if (val >= _in[size-1])
|
||||
else if (value >= _in[size-1])
|
||||
{
|
||||
cache = _out[size-1];
|
||||
}
|
||||
@ -75,17 +77,17 @@ T multiMap(T val, T* _in, T* _out, uint8_t size)
|
||||
{
|
||||
// search right interval; index 0 _in[0] already tested
|
||||
uint8_t pos = 1;
|
||||
while(val > _in[pos]) pos++;
|
||||
while(value > _in[pos]) pos++;
|
||||
|
||||
// this will handle all exact "points" in the _in array
|
||||
if (val == _in[pos])
|
||||
if (value == _in[pos])
|
||||
{
|
||||
cache = _out[pos];
|
||||
}
|
||||
else
|
||||
{
|
||||
// interpolate in the right segment for the rest
|
||||
cache = (val - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
|
||||
cache = (value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
|
||||
}
|
||||
}
|
||||
return cache;
|
||||
@ -94,3 +96,4 @@ T multiMap(T val, T* _in, T* _out, uint8_t size)
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
|
||||
[![Arduino CI](https://github.com/RobTillaart/MultiMap/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
|
||||
[![Arduino-lint](https://github.com/RobTillaart/MultiMap/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/MultiMap/actions/workflows/arduino-lint.yml)
|
||||
[![JSON check](https://github.com/RobTillaart/MultiMap/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/MultiMap/actions/workflows/jsoncheck.yml)
|
||||
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/MultiMap/blob/master/LICENSE)
|
||||
[![GitHub release](https://img.shields.io/github/release/RobTillaart/MultiMap.svg?maxAge=3600)](https://github.com/RobTillaart/MultiMap/releases)
|
||||
|
||||
|
||||
# MultiMap
|
||||
|
||||
Arduino library for fast non-linear mapping or interpolation of values
|
||||
@ -12,7 +15,8 @@ Arduino library for fast non-linear mapping or interpolation of values
|
||||
|
||||
In Arduino applications often the value of a sensor is mapped upon a more
|
||||
usable value. E.g. the value of analogRead() is mapped onto 0 .. 5.0 Volt.
|
||||
This is done by the map function which does a linear interpolation. This means
|
||||
This is done by the map function which does a linear interpolation.
|
||||
This means in code:
|
||||
|
||||
```cpp
|
||||
output = C1 + input * C2
|
||||
@ -25,10 +29,11 @@ two variables runtime from two given mappings.
|
||||
output = map(input, I1, I2, O1, O2):
|
||||
```
|
||||
|
||||
In many cases when there is no linear mapping possible, as the 'points' are not on a single line.
|
||||
One needs non-linear math to calculate the output, **Multimap()** just does that.
|
||||
In many cases when there is no linear mapping possible, as the 'points' are not on a single straight line.
|
||||
One needs non-linear math to calculate the output, **Multimap()** just simulates that.
|
||||
|
||||
**out = Multimap(value, input, output, size)** needs two equal sized arrays of reference 'points', **input\[\]** and **output\[\]**, it looks up the
|
||||
**out = Multimap(value, input, output, size)** needs two equal sized arrays of reference 'points',
|
||||
**input\[\]** and **output\[\]**, it looks up the
|
||||
input value in the input\[\] array and if needed it linear interpolates between two
|
||||
points of the output\[\] array.
|
||||
|
||||
@ -44,6 +49,15 @@ See examples
|
||||
Please note the fail example as this shows that in the intern math overflow can happen.
|
||||
|
||||
|
||||
## TODO
|
||||
## Future
|
||||
|
||||
- Investigate class implementation for performance / footprint
|
||||
- flag if input value was "IN_MIN" < input < "IN_MAX",
|
||||
now it is constrained without user being informed.
|
||||
- extend unit tests
|
||||
|
||||
|
||||
**wont**
|
||||
- should the lookup tables be merged into one array of pairs?
|
||||
- you cannot reuse e.g. the input array then. (memory footprint)
|
||||
|
||||
Investigate class implementation for performance.
|
||||
|
@ -1,11 +1,11 @@
|
||||
//
|
||||
// FILE: multimap_NTC.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: demo
|
||||
// DATE: 2020-04-09
|
||||
// (c) : MIT
|
||||
//
|
||||
// example uses multiMap to calculate the temperature from an 10K NTC.
|
||||
|
||||
|
||||
#include "MultiMap.h"
|
||||
@ -22,11 +22,13 @@ volatile float x, y, z;
|
||||
float in[] = {
|
||||
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
|
||||
};
|
||||
|
||||
float out[] = {
|
||||
-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,
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
int sz = 33;
|
||||
|
||||
|
||||
@ -87,3 +89,4 @@ float val(int sensorValueA1)
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -1,16 +1,15 @@
|
||||
//
|
||||
// FILE: multimap_NTC_int_FAIL.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: demo of faulty optimizing
|
||||
// DATE: 2020-04-09
|
||||
// (c) : MIT
|
||||
//
|
||||
|
||||
//
|
||||
// NOTE:
|
||||
// use integers instead of floats to minimize RAM. uses ~320 bytes PROGMEM ~120 bytes RAM less on UNO than float version
|
||||
//
|
||||
// this example is added to show how to reduce memory but also how it can FAIL due to math overflow
|
||||
// this example is added to show how to reduce memory but also how it can FAIL due to math overflow
|
||||
// E.g. see around 196-200; 340-400
|
||||
// to prevent this one must have more values which increases the memory usage again.
|
||||
//
|
||||
@ -27,6 +26,7 @@ volatile float x, y, z;
|
||||
int in[] = {
|
||||
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
|
||||
};
|
||||
|
||||
int out[] = {
|
||||
-27315, -7165, -6069, -4981, -4397, -3850, -3554, -3216, -2572, -2295, -2008, -1737, -1462, -790, -143, 357, 808, 1634, 2430, 3264,
|
||||
3717, 4213, 4805, 5419, 5875, 6603, 7287, 8385, 9651, 11146, 12949, 18282, 30182
|
||||
@ -91,3 +91,4 @@ float val(int sensorValueA1)
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
//
|
||||
// FILE: multimap_distance.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: demo
|
||||
// DATE: 2020-04-09
|
||||
//
|
||||
// example simulates the lookup graph of a distance sensor
|
||||
|
||||
|
||||
#include "MultiMap.h"
|
||||
@ -48,3 +48,4 @@ float sharp2cm(int val)
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
//
|
||||
// FILE: multimap_functions.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: demo (use serial plotter)...
|
||||
// DATE: 2020-04-09
|
||||
// (c) : MIT
|
||||
//
|
||||
// example show use of multiMap to approximate some well known functions.
|
||||
|
||||
|
||||
|
||||
#include "MultiMap.h"
|
||||
@ -53,7 +54,7 @@ void test_normal_distribution()
|
||||
|
||||
void test_sinus()
|
||||
{
|
||||
// one sinus wave, amplitudo 1023
|
||||
// one sinus wave, amplitude 1023
|
||||
long sinus[] = {0, 316, 601, 827, 972, 1023, 972, 827, 601, 316, 0, -316, -601, -827, -972, -1023, -972, -827, -601, -316, 0 }; //21
|
||||
long in[21];
|
||||
for (int i = 0; i < 21; i++) in[i] = round(i * 1000.0 / 20);
|
||||
@ -136,3 +137,4 @@ void test_sawtooth()
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
//
|
||||
// FILE: multimap_timing.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: demo
|
||||
// DATE: 2020-04-09
|
||||
// (c) : MIT
|
||||
//
|
||||
// example measures the performance of multiMap <int> vs <float>
|
||||
|
||||
|
||||
#include "MultiMap.h"
|
||||
@ -30,6 +30,7 @@ void setup()
|
||||
start = micros();
|
||||
float x = multiMap<int>(12, in, out, 3);
|
||||
stop = micros();
|
||||
Serial.print("time <int>: \t");
|
||||
Serial.println(stop - start);
|
||||
Serial.println(x, 4);
|
||||
delay(10); // make sure print has ended
|
||||
@ -37,8 +38,12 @@ void setup()
|
||||
start = micros();
|
||||
float y = multiMap<float>(12, fin, fout, 3);
|
||||
stop = micros();
|
||||
Serial.print("time <float>: \t");
|
||||
Serial.println(stop - start);
|
||||
Serial.println(y, 4);
|
||||
delay(10); // make sure print has ended
|
||||
|
||||
Serial.println("\ndone...");
|
||||
}
|
||||
|
||||
|
||||
@ -48,3 +53,4 @@ void loop()
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Syntax Coloring Map For multiMap
|
||||
# Syntax Colouring Map For multiMap
|
||||
|
||||
# Datatypes (KEYWORD1)
|
||||
# Data types (KEYWORD1)
|
||||
|
||||
|
||||
# Methods and Functions (KEYWORD2)
|
||||
|
@ -15,8 +15,9 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/MultiMap.git"
|
||||
},
|
||||
"version": "0.1.4",
|
||||
"version": "0.1.5",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
"platforms": "*",
|
||||
"headers": "MultiMap.h"
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=MultiMap
|
||||
version=0.1.4
|
||||
version=0.1.5
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Library for fast non-linear interpolation by means of two arrays.
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
unittest_setup()
|
||||
{
|
||||
fprintf(stderr, "MULTIMAP_LIB_VERSION: %s\n", (char *) MULTIMAP_LIB_VERSION);
|
||||
}
|
||||
|
||||
|
||||
@ -58,10 +59,8 @@ unittest(test_new_operator)
|
||||
*/
|
||||
|
||||
|
||||
unittest(test_all)
|
||||
unittest(test_float)
|
||||
{
|
||||
fprintf(stderr, "VERSION: %s\n", MULTIMAP_LIB_VERSION);
|
||||
|
||||
// based on the distance example
|
||||
// out[] holds the distances in cm
|
||||
float out[] = {150, 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40, 30, 20};
|
||||
@ -78,6 +77,25 @@ unittest(test_all)
|
||||
}
|
||||
|
||||
|
||||
/* todo
|
||||
unittest(test_uint32_t)
|
||||
{
|
||||
// based on the distance example
|
||||
// out[] holds the distances in cm
|
||||
uint32_t out[] = {150, 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40, 30, 20};
|
||||
// in[] holds the measured analogRead() values for that distance
|
||||
uint32_t in[] = { 90, 97, 105, 113, 124, 134, 147, 164, 185, 218, 255, 317, 408, 506};
|
||||
|
||||
assertEqual(150, multiMap<uint32_t>(80, in, out, 14) );
|
||||
assertEqual(136, multiMap<uint32_t>(100, in, out, 14) );
|
||||
assertEqual( 65, multiMap<uint32_t>(200, in, out, 14) );
|
||||
assertEqual( 42, multiMap<uint32_t>(300, in, out, 14) );
|
||||
assertEqual( 30, multiMap<uint32_t>(400, in, out, 14) );
|
||||
assertEqual( 20, multiMap<uint32_t>(500, in, out, 14) );
|
||||
assertEqual( 20, multiMap<uint32_t>(600, in, out, 14) );
|
||||
}
|
||||
*/
|
||||
|
||||
unittest_main()
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user