0.1.4 map2colour

This commit is contained in:
rob tillaart 2021-12-09 15:05:02 +01:00
parent f97f14dfd9
commit b0515db518
17 changed files with 1474 additions and 55 deletions

View File

@ -8,62 +8,163 @@
# map2colour
Arduino library for mapping a float to colour spectrum
Arduino library for mapping a float to colour spectrum.
## Description
The map2colour library is used to make map a reading from a sensor, e.g. temperature or pressure,
to a colour in the RGB spectrum.
The map2colour library is used to make map a reading from a sensor, e.g. temperature or pressure,
to a colour in the RGB spectrum. This can be used to colour an element on a graphical display, drive an RGB LED, or even a LED string etc.
The initial release uses 7 floats values that describe the range being mapped.
These are passed to the library with **begin()**.
These 7 floats must be in ascending order and are mapped upon the following colour array.
The initial release uses 7 floats values that describe the range being mapped.
These are passed to the library with **begin()**.
These 7 floats must be in ascending order and are mapped default on the following colour array.
```cpp
uint32_t colours[] =
uint32_t colours[] =
{
// BLACK RED YELLOW GREEN ?? BLUE WHITE
// BLACK RED YELLOW GREEN AQUA BLUE WHITE
0x00000000, 0x00FF0000, 0x00FFFF00, 0x0000FF00, 0x0000FFFF, 0x000000FF, 0x00FFFFFF
}
```
New values will be linear interpolated between the two points when needed.
New values will be linear interpolated between two points when needed.
Assume you initialize a float array
Assume you initialize a float array
```cpp
float tempArray[] = { -10, -10, 5, 15, 30, 60, 125 }; // note the double -10
float tempArray[] = { -20, -10, 5, 15, 30, 60, 125 };
```
A temperature of 0°C will be mapped between the 2nd and 3rd element so somewhere
between RED and YELLOW.
A temperature between 60°C and 125°C will be mapped between BLUE and WHITE.
A temperature of 0°C will be mapped between the 2nd and 3rd element so
between RED and YELLOW.
A temperature between 60°C and 125°C will be mapped between BLUE and WHITE.
This first version is to get hands on experience, a later version should
support user defined colour maps.
**begin()** also allows one to overrule the colours array with a colour array of your choice.
Adjusting the colour array allows one to use a "full spectrum" like the default or only
interpolate between two colours. Note the library has several colours predefined as constant
to make the colour table (and the code) more readable. If colours are missing please make a
PullRequest (preferred) or file an issue.
**begin()** returns false if the array of values is not in increasing order, true otherwise.
If returned false the code might behave in unexpected ways.
## Interface
- **map2colour()** constructor.
- **bool begin(float \* ar)** load the array with 7 boundaries.
- **uint32_t map2RGB(float value)** returns RGB colour packed in an uint32_t. **0x00RRGGBB**
- **map2colourFast()** constructor, (larger code base, more RAM and faster)
- **bool begin(float \* values, uint32_t \* colourMap = NULL)** load the array with **7**
boundary values and the associated array of **7** colours packed in uint32_t **0x00RRGGBB**.
If the colour array is not given the last given (or the default) colour array is used.
**begin()** can be called multiple times to change the mapping.
The function returns false if the array of values is not in increasing order.
- **uint32_t map2RGB(float value)** returns RGB colour packed in an uint32_t **0x00RRGGBB**.
If the value is out of range of the original values array, the value is always mapped upon the first colour.
- **uint16_t map2_565(float value)** often used 16 bit colour format. Currently a wrapper around **map2RGB**.
Note: the arrays passed to **begin()** should both have at least 7 elements!
The colour array can be filled with decimal or HEX values or predefined colours can be used. See below.
## Predefined colours
Colours are represented as 24 bit RGB values and have the pattern **0x00RRGGBB**.
| define | value |
|:------------|:----------:|
| M2C_BLACK | 0x00000000 |
| M2C_SILVER | 0x00C0C0C0 |
| M2C_GRAY | 0x00808080 |
| M2C_WHITE | 0x00FFFFFF |
| M2C_MAROON | 0x00800000 |
| M2C_RED | 0x00FF0000 |
| M2C_PURPLE | 0x00800080 |
| M2C_FUCHSIA | 0x00FF00FF |
| M2C_GREEN | 0x00008000 |
| M2C_LIME | 0x000FF000 |
| M2C_OLIVE | 0x00808000 |
| M2C_YELLOW | 0x00FFFF00 |
| M2C_NAVY | 0x00000080 |
| M2C_BLUE | 0x000000FF |
| M2C_TEAL | 0x00008080 |
| M2C_AQUA | 0x0000FFFF |
More colour definitions can be found on the internet e.g. https://www.w3.org/wiki/CSS/Properties/color/keywords
## Operation
See examples.
By changing the colour map one can get different effects.
The minimum to implement is an intensity effect going from black towards a colour at max intensity.
More complex colour schemes are possible, up to 7 different colours.
This number is hardcoded (for now) and that might change in the future.
## Performance
Indicative performance figures measured with performance example.
Performance depends on colours chosen, platform etc.
#### version 0.1.2
| function call | time us UNO | time us ESP32 |
|:-----------------------|------------:|--------------:|
| begin(values) | 4 | 4 |
| begin(values, colours) | 12 | 4 |
| map2RGB(value) | 124 - 152 | 2 - 4 |
| map2_565(value) | 124 - 168 | 2 - 4 |
#### version 0.1.3
| function call | time us UNO | time us ESP32 |
|:-----------------------|------------:|--------------:|
| begin(values) | 4 | 4 |
| begin(values, colours) | 12 | 4 |
| map2RGB(value) | 64 - 132 | 2 - 3 |
| map2_565(value) | 68 - 140 | 2 - 3 |
#### version 0.1.4
| function call | time us UNO | time us ESP32 | notes |
|:-----------------------|------------:|--------------:|:----------------------|
| begin(values) | 284 | 15 | unexpected peak ESP32 |
| begin(values, colours) | 304 | 6 |
| map2RGB(value) | 40 - 104 | 1 - 2 |
| map2_565(value) | 44 - 112 | 1 - 2 |
Note: UNO at 16 MHz, ESP32 at 240 MHz
#### optimization 0.1.4
One performance optimization (trade memory for speed) is replacing the float division
in map2RGB by a multiplication.
This requires 24 bytes RAM to hold the 6 factors and ~100 bytes of PROGMEM for the calculation of the dividers in begin().
This optimization is implemented as a derived class **map2colourFast** in version 0.1.4.
The **map2RGB()** call is about 40 % faster compared to the original 0.1.2.
Although the **begin()** call is ~300 us longer, it only takes a dozen **map2RGB()** calls to break even.
Note: the gain for the ESP32 is less pronounced, but can still be interesting.
## Future
- update documentation
**0.2.0** thoughts
- make the colour map user defined - like multi-map
- between BLACK and a single colour. - intensity
- between a number of colours e.g. RED YELLOW GREEN or GREEN YELLOW RED
- fixed number of points is flex enough
- example with double entries
- temp -10, 5, 10, 30, 35, 60, 120
- Red yellow black black yellow red red
- middle area 10..30 has no colour.
#### development ?
- **void adjustColour(uint8_t index, uint32_t RGB)** // single colour adjust
- **uint32_t dumpColourMap()**
- PROGMEM for default array?

View File

@ -10,6 +10,7 @@
#include "Arduino.h"
#include "map2colour.h"
map2colour mc;
// should be in increasing order
@ -32,8 +33,7 @@ void setup()
Serial.print("\t");
Serial.println(rgb, HEX);
}
Serial.println("done...");
Serial.println();
}

View File

@ -0,0 +1,51 @@
//
// FILE: map2colour_faucet.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: map2colour demo
// DATE: 2021-12-06
// URL: https://github.com/RobTillaart/map2colour
// demo simulates a temperature of a faucet mapped upon 2 colours.
// blue = cold, black is middle, red is hot
#include "Arduino.h"
#include "map2colour.h"
map2colour mct;
// values must be 7 elements in increasing order.
float values[7] = { 0, 10, 15, 25, 40, 100, 125 };
uint32_t faucet[7] =
{
M2C_BLUE, M2C_BLUE, M2C_BLACK, M2C_BLACK, M2C_RED, M2C_RED, M2C_RED
};
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
mct.begin(values, faucet);
for (int i = -20; i < 125; i++)
{
uint32_t rgb = mct.map2RGB(i);
Serial.print(i);
Serial.print("\t");
Serial.println(rgb, HEX);
}
Serial.println();
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,51 @@
//
// FILE: map2colour_intensity.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: map2colour demo
// DATE: 2021-12-06
// URL: https://github.com/RobTillaart/map2colour
// demo simulates a temperature mapped upon 1 colour intensity.
// low temperature = no colour, higher is more intense RED
#include "Arduino.h"
#include "map2colour.h"
map2colour mct;
// values must be 7 elements in increasing order
float values[7] = { 20, 100, 125, 150, 200, 250, 300 };
uint32_t colours[7] =
{
M2C_BLACK, M2C_RED, M2C_RED, M2C_RED, M2C_RED, M2C_RED, M2C_RED
};
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
mct.begin(values, colours);
for (int i = -20; i < 125; i++)
{
uint32_t rgb = mct.map2RGB(i);
Serial.print(i);
Serial.print("\t");
Serial.println(rgb, HEX);
}
Serial.println();
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,51 @@
//
// FILE: map2colour_map2_565.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: map2colour demo
// DATE: 2021-12-05
// URL: https://github.com/RobTillaart/map2colour
#include "Arduino.h"
#include "map2colour.h"
map2colour mc;
// should be in increasing order
float values[7] = { 0, 32, 64, 128, 256, 512, 1024 };
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
// load the values array
mc.begin(values);
// show the interpolating
for (float i = 0; i < 1024; i += 10)
{
uint16_t rgb = mc.map2_565(i);
Serial.print(i);
Serial.print("\t");
Serial.println(rgb, HEX);
}
Serial.println();
}
void loop()
{
int x = analogRead(0); // UNO returns between 0..1023; adapt if needed.
uint32_t rgb = mc.map2_565(x);
Serial.print(x);
Serial.print("\t");
Serial.println(rgb, HEX);
delay(100);
}
// -- END OF FILE --

View File

@ -0,0 +1,97 @@
//
// FILE: map2colour_performance.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: map2colour demo
// DATE: 2021-12-04
// URL: https://github.com/RobTillaart/map2colour
#include "Arduino.h"
#include "map2colour.h"
map2colour mc;
// map2colourFast mc;
// should be in increasing order; and 7 elements
float values[7] = { 0, 32, 64, 128, 256, 512, 1024 };
uint32_t colours[7] =
{
M2C_RED, M2C_RED, M2C_YELLOW, M2C_LIME, M2C_YELLOW, M2C_RED, M2C_RED
};
uint32_t start, stop;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.println("begin()");
delay(10);
// use the default colour map.
start = micros();
mc.begin(values);
stop = micros();
Serial.println(stop - start);
delay(10);
// use the default colour map.
start = micros();
mc.begin(values, colours);
stop = micros();
Serial.println(stop - start);
Serial.println();
delay(1000);
Serial.println("map2RGB()");
delay(10);
for (float i = 0; i < 1024; i += 10)
{
start = micros();
uint32_t rgb = mc.map2RGB(i);
stop = micros();
Serial.print(stop - start); // 120 - 172 us
Serial.print("\t");
Serial.print(i);
Serial.print("\t");
Serial.println(rgb, HEX);
delay(10);
}
Serial.println();
delay(1000);
Serial.println("map2_565()");
delay(10);
for (float i = 0; i < 1024; i += 10)
{
uint32_t start = micros();
uint32_t rgb = mc.map2_565(i);
uint32_t stop = micros();
Serial.print(stop - start); // 120 - 172 us
Serial.print("\t");
Serial.print(i);
Serial.print("\t");
Serial.println(rgb, HEX);
delay(10);
}
Serial.println();
Serial.println("done...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,217 @@
map2colour_performance.ino
begin()
4
12
map2RGB()
28 0.00 FF0000
132 10.00 FF0000
132 20.00 FF0000
136 30.00 FF0000
148 40.00 FF3F00
140 50.00 FF8F00
144 60.00 FFDF00
164 70.00 E8FD00
160 80.00 C3FB00
156 90.00 9DF800
160 100.00 78F600
156 110.00 52F400
160 120.00 2DF100
168 130.00 12F000
164 140.00 25F100
164 150.00 38F200
168 160.00 4BF300
168 170.00 5DF400
164 180.00 70F600
160 190.00 83F700
164 200.00 96F800
164 210.00 A8F900
164 220.00 BBFA00
172 230.00 CEFB00
168 240.00 E1FD00
168 250.00 F3FE00
164 260.00 FFFB00
160 270.00 FFF100
160 280.00 FFE700
160 290.00 FFDD00
160 300.00 FFD300
168 310.00 FFC900
160 320.00 FFBF00
160 330.00 FFB500
156 340.00 FFAB00
160 350.00 FFA100
160 360.00 FF9700
156 370.00 FF8D00
164 380.00 FF8300
160 390.00 FF7900
160 400.00 FF6F00
160 410.00 FF6500
160 420.00 FF5B00
160 430.00 FF5100
156 440.00 FF4700
168 450.00 FF3D00
164 460.00 FF3300
160 470.00 FF2900
160 480.00 FF1F00
164 490.00 FF1500
164 500.00 FF0B00
168 510.00 FF0100
164 520.00 FF0000
164 530.00 FF0000
156 540.00 FF0000
156 550.00 FF0000
156 560.00 FF0000
156 570.00 FF0000
156 580.00 FF0000
160 590.00 FF0000
160 600.00 FF0000
160 610.00 FF0000
160 620.00 FF0000
156 630.00 FF0000
156 640.00 FF0000
160 650.00 FF0000
156 660.00 FF0000
160 670.00 FF0000
156 680.00 FF0000
156 690.00 FF0000
156 700.00 FF0000
156 710.00 FF0000
156 720.00 FF0000
156 730.00 FF0000
164 740.00 FF0000
156 750.00 FF0000
156 760.00 FF0000
160 770.00 FF0000
156 780.00 FF0000
156 790.00 FF0000
156 800.00 FF0000
160 810.00 FF0000
160 820.00 FF0000
156 830.00 FF0000
160 840.00 FF0000
156 850.00 FF0000
156 860.00 FF0000
160 870.00 FF0000
160 880.00 FF0000
156 890.00 FF0000
156 900.00 FF0000
156 910.00 FF0000
156 920.00 FF0000
156 930.00 FF0000
156 940.00 FF0000
164 950.00 FF0000
160 960.00 FF0000
160 970.00 FF0000
160 980.00 FF0000
160 990.00 FF0000
160 1000.00 FF0000
160 1010.00 FF0000
168 1020.00 FF0000
map2_565()
24 0.00 F800
136 10.00 F800
136 20.00 F800
140 30.00 F800
152 40.00 F9E0
148 50.00 FC60
148 60.00 FEE0
164 70.00 EFE0
160 80.00 C7C0
160 90.00 9FC0
160 100.00 7FA0
168 110.00 57A0
164 120.00 2F80
172 130.00 1780
168 140.00 2780
168 150.00 3F80
168 160.00 4F80
168 170.00 5FA0
168 180.00 77A0
168 190.00 87A0
164 200.00 97C0
168 210.00 AFC0
168 220.00 BFC0
168 230.00 CFC0
172 240.00 E7E0
172 250.00 F7E0
168 260.00 FFC0
168 270.00 FF80
172 280.00 FF20
164 290.00 FEE0
164 300.00 FE80
164 310.00 FE40
164 320.00 FDE0
164 330.00 FDA0
164 340.00 FD40
164 350.00 FD00
164 360.00 FCA0
168 370.00 FC60
164 380.00 FC00
164 390.00 FBC0
164 400.00 FB60
168 410.00 FB20
164 420.00 FAC0
164 430.00 FA80
164 440.00 FA20
172 450.00 F9E0
164 460.00 F980
164 470.00 F940
168 480.00 F8E0
168 490.00 F8A0
172 500.00 F840
172 510.00 F800
160 520.00 F800
160 530.00 F800
168 540.00 F800
160 550.00 F800
160 560.00 F800
160 570.00 F800
164 580.00 F800
164 590.00 F800
160 600.00 F800
160 610.00 F800
160 620.00 F800
160 630.00 F800
160 640.00 F800
160 650.00 F800
160 660.00 F800
160 670.00 F800
160 680.00 F800
160 690.00 F800
160 700.00 F800
168 710.00 F800
160 720.00 F800
160 730.00 F800
164 740.00 F800
168 750.00 F800
160 760.00 F800
164 770.00 F800
160 780.00 F800
160 790.00 F800
160 800.00 F800
164 810.00 F800
160 820.00 F800
164 830.00 F800
160 840.00 F800
160 850.00 F800
164 860.00 F800
160 870.00 F800
168 880.00 F800
160 890.00 F800
164 900.00 F800
164 910.00 F800
168 920.00 F800
164 930.00 F800
164 940.00 F800
164 950.00 F800
164 960.00 F800
164 970.00 F800
164 980.00 F800
164 990.00 F800
164 1000.00 F800
172 1010.00 F800
164 1020.00 F800
done...

View File

@ -0,0 +1,217 @@
map2colour_performance.ino
begin()
4
12
map2RGB()
20 0.00 FF0000
68 10.00 FF0000
68 20.00 FF0000
64 30.00 FF0000
96 40.00 FF3F00
96 50.00 FF8F00
104 60.00 FFDF00
128 70.00 E8FD00
128 80.00 C3FB00
124 90.00 9DF800
124 100.00 78F600
128 110.00 52F400
132 120.00 2DF100
128 130.00 12F000
128 140.00 25F100
128 150.00 38F200
132 160.00 4BF300
124 170.00 5DF400
128 180.00 70F600
128 190.00 83F700
128 200.00 96F800
128 210.00 A8F900
132 220.00 BBFA00
128 230.00 CEFB00
132 240.00 E1FD00
128 250.00 F3FE00
108 260.00 FFFB00
104 270.00 FFF100
108 280.00 FFE700
108 290.00 FFDD00
104 300.00 FFD300
104 310.00 FFC900
108 320.00 FFBF00
104 330.00 FFB500
104 340.00 FFAB00
104 350.00 FFA100
104 360.00 FF9700
104 370.00 FF8D00
108 380.00 FF8300
108 390.00 FF7900
104 400.00 FF6F00
108 410.00 FF6500
108 420.00 FF5B00
112 430.00 FF5100
108 440.00 FF4700
108 450.00 FF3D00
108 460.00 FF3300
108 470.00 FF2900
112 480.00 FF1F00
108 490.00 FF1500
108 500.00 FF0B00
112 510.00 FF0100
92 520.00 FF0000
96 530.00 FF0000
88 540.00 FF0000
88 550.00 FF0000
88 560.00 FF0000
92 570.00 FF0000
88 580.00 FF0000
88 590.00 FF0000
88 600.00 FF0000
88 610.00 FF0000
88 620.00 FF0000
88 630.00 FF0000
84 640.00 FF0000
88 650.00 FF0000
88 660.00 FF0000
88 670.00 FF0000
88 680.00 FF0000
88 690.00 FF0000
88 700.00 FF0000
88 710.00 FF0000
88 720.00 FF0000
88 730.00 FF0000
88 740.00 FF0000
88 750.00 FF0000
92 760.00 FF0000
88 770.00 FF0000
88 780.00 FF0000
88 790.00 FF0000
92 800.00 FF0000
88 810.00 FF0000
88 820.00 FF0000
88 830.00 FF0000
88 840.00 FF0000
88 850.00 FF0000
88 860.00 FF0000
92 870.00 FF0000
88 880.00 FF0000
88 890.00 FF0000
88 900.00 FF0000
88 910.00 FF0000
88 920.00 FF0000
88 930.00 FF0000
88 940.00 FF0000
88 950.00 FF0000
88 960.00 FF0000
88 970.00 FF0000
92 980.00 FF0000
96 990.00 FF0000
88 1000.00 FF0000
92 1010.00 FF0000
92 1020.00 FF0000
map2_565()
20 0.00 F800
76 10.00 F800
68 20.00 F800
72 30.00 F800
96 40.00 F9E0
100 50.00 FC60
108 60.00 FEE0
128 70.00 EFE0
128 80.00 C7C0
128 90.00 9FC0
132 100.00 7FA0
132 110.00 57A0
132 120.00 2F80
136 130.00 1780
132 140.00 2780
132 150.00 3F80
128 160.00 4F80
128 170.00 5FA0
128 180.00 77A0
132 190.00 87A0
136 200.00 97C0
132 210.00 AFC0
132 220.00 BFC0
132 230.00 CFC0
140 240.00 E7E0
128 250.00 F7E0
112 260.00 FFC0
112 270.00 FF80
108 280.00 FF20
112 290.00 FEE0
108 300.00 FE80
116 310.00 FE40
108 320.00 FDE0
108 330.00 FDA0
108 340.00 FD40
108 350.00 FD00
108 360.00 FCA0
108 370.00 FC60
116 380.00 FC00
108 390.00 FBC0
108 400.00 FB60
108 410.00 FB20
108 420.00 FAC0
108 430.00 FA80
112 440.00 FA20
116 450.00 F9E0
108 460.00 F980
108 470.00 F940
112 480.00 F8E0
112 490.00 F8A0
112 500.00 F840
116 510.00 F800
96 520.00 F800
92 530.00 F800
92 540.00 F800
92 550.00 F800
92 560.00 F800
88 570.00 F800
92 580.00 F800
92 590.00 F800
92 600.00 F800
92 610.00 F800
92 620.00 F800
92 630.00 F800
92 640.00 F800
92 650.00 F800
96 660.00 F800
88 670.00 F800
92 680.00 F800
96 690.00 F800
88 700.00 F800
88 710.00 F800
92 720.00 F800
92 730.00 F800
92 740.00 F800
92 750.00 F800
92 760.00 F800
92 770.00 F800
92 780.00 F800
92 790.00 F800
92 800.00 F800
92 810.00 F800
92 820.00 F800
96 830.00 F800
92 840.00 F800
92 850.00 F800
92 860.00 F800
92 870.00 F800
92 880.00 F800
92 890.00 F800
92 900.00 F800
92 910.00 F800
92 920.00 F800
96 930.00 F800
92 940.00 F800
92 950.00 F800
92 960.00 F800
100 970.00 F800
92 980.00 F800
92 990.00 F800
100 1000.00 F800
92 1010.00 F800
92 1020.00 F800
done...

View File

@ -0,0 +1,217 @@
map2colour_performance.ino - map2colourFast
begin()
220
232
map2RGB()
16 0.00 FF0000
44 10.00 FF0000
40 20.00 FF0000
44 30.00 FF0000
68 40.00 FF3F00
68 50.00 FF8F00
72 60.00 FFDF00
100 70.00 E8FD00
100 80.00 C3FB00
100 90.00 9DF800
104 100.00 78F600
100 110.00 52F400
108 120.00 2DF100
100 130.00 12F000
104 140.00 25F100
100 150.00 38F200
100 160.00 4BF300
104 170.00 5DF400
100 180.00 70F600
104 190.00 83F700
104 200.00 96F800
100 210.00 A8F900
100 220.00 BBFA00
104 230.00 CEFB00
108 240.00 E1FD00
104 250.00 F3FE00
80 260.00 FFFB00
84 270.00 FFF100
80 280.00 FFE700
80 290.00 FFDD00
80 300.00 FFD300
84 310.00 FFC900
80 320.00 FFBF00
80 330.00 FFB500
88 340.00 FFAB00
80 350.00 FFA100
80 360.00 FF9700
80 370.00 FF8D00
80 380.00 FF8300
80 390.00 FF7900
80 400.00 FF6F00
80 410.00 FF6500
80 420.00 FF5B00
80 430.00 FF5100
84 440.00 FF4700
80 450.00 FF3D00
80 460.00 FF3300
80 470.00 FF2900
84 480.00 FF1F00
92 490.00 FF1500
84 500.00 FF0B00
88 510.00 FF0100
64 520.00 FF0000
64 530.00 FF0000
60 540.00 FF0000
60 550.00 FF0000
60 560.00 FF0000
64 570.00 FF0000
64 580.00 FF0000
64 590.00 FF0000
64 600.00 FF0000
64 610.00 FF0000
64 620.00 FF0000
64 630.00 FF0000
64 640.00 FF0000
64 650.00 FF0000
64 660.00 FF0000
64 670.00 FF0000
64 680.00 FF0000
64 690.00 FF0000
64 700.00 FF0000
60 710.00 FF0000
64 720.00 FF0000
64 730.00 FF0000
64 740.00 FF0000
64 750.00 FF0000
60 760.00 FF0000
60 770.00 FF0000
64 780.00 FF0000
64 790.00 FF0000
64 800.00 FF0000
64 810.00 FF0000
64 820.00 FF0000
64 830.00 FF0000
64 840.00 FF0000
64 850.00 FF0000
64 860.00 FF0000
60 870.00 FF0000
64 880.00 FF0000
64 890.00 FF0000
64 900.00 FF0000
64 910.00 FF0000
64 920.00 FF0000
64 930.00 FF0000
64 940.00 FF0000
64 950.00 FF0000
64 960.00 FF0000
64 970.00 FF0000
64 980.00 FF0000
64 990.00 FF0000
64 1000.00 FF0000
68 1010.00 FF0000
72 1020.00 FF0000
map2_565()
16 0.00 F800
48 10.00 F800
48 20.00 F800
48 30.00 F800
76 40.00 F9E0
72 50.00 FC60
72 60.00 FEE0
104 70.00 EFE0
104 80.00 C7C0
104 90.00 9FC0
104 100.00 7FA0
108 110.00 57A0
108 120.00 2F80
108 130.00 1780
104 140.00 2780
104 150.00 3F80
104 160.00 4F80
108 170.00 5FA0
108 180.00 77A0
108 190.00 87A0
104 200.00 97C0
104 210.00 AFC0
104 220.00 BFC0
108 230.00 CFC0
116 240.00 E7E0
108 250.00 F7E0
84 260.00 FFC0
92 270.00 FF80
84 280.00 FF20
84 290.00 FEE0
84 300.00 FE80
84 310.00 FE40
84 320.00 FDE0
84 330.00 FDA0
84 340.00 FD40
84 350.00 FD00
84 360.00 FCA0
84 370.00 FC60
92 380.00 FC00
88 390.00 FBC0
84 400.00 FB60
84 410.00 FB20
84 420.00 FAC0
84 430.00 FA80
88 440.00 FA20
84 450.00 F9E0
88 460.00 F980
88 470.00 F940
84 480.00 F8E0
88 490.00 F8A0
88 500.00 F840
92 510.00 F800
68 520.00 F800
68 530.00 F800
64 540.00 F800
68 550.00 F800
64 560.00 F800
64 570.00 F800
68 580.00 F800
64 590.00 F800
64 600.00 F800
64 610.00 F800
68 620.00 F800
64 630.00 F800
64 640.00 F800
72 650.00 F800
64 660.00 F800
68 670.00 F800
68 680.00 F800
68 690.00 F800
64 700.00 F800
68 710.00 F800
64 720.00 F800
72 730.00 F800
64 740.00 F800
68 750.00 F800
68 760.00 F800
68 770.00 F800
68 780.00 F800
64 790.00 F800
68 800.00 F800
68 810.00 F800
64 820.00 F800
68 830.00 F800
68 840.00 F800
64 850.00 F800
72 860.00 F800
68 870.00 F800
64 880.00 F800
68 890.00 F800
68 900.00 F800
68 910.00 F800
68 920.00 F800
68 930.00 F800
72 940.00 F800
68 950.00 F800
68 960.00 F800
72 970.00 F800
68 980.00 F800
68 990.00 F800
72 1000.00 F800
68 1010.00 F800
68 1020.00 F800
done...

View File

@ -0,0 +1,58 @@
//
// FILE: map2colour_pressure.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: map2colour demo
// DATE: 2021-12-05
// URL: https://github.com/RobTillaart/map2colour
// demo simulates a pressure sensor and its mapping on three colours
// pressure 950, 990, 1010, 1030 1050, 2000, 2000
// RED YELLOW GREEN YELLOW RED WHITE WHITE
#include "Arduino.h"
#include "map2colour.h"
map2colour mcp;
// should be in increasing order; and 7 elements
// pressure in mbar
float values[7] = { 950, 990, 1010, 1030, 1050, 2000, 2500 };
uint32_t colours[7] =
{
M2C_RED, M2C_YELLOW, M2C_GREEN, M2C_YELLOW, M2C_RED, M2C_WHITE, M2C_WHITE
};
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
mcp.begin(values, colours);
for (int i = 950; i < 1050; i++)
{
uint32_t rgb = mcp.map2RGB(i);
Serial.print(i);
Serial.print("\t");
Serial.println(rgb, HEX);
}
Serial.println();
}
void loop()
{
float pressure = 950 + random(100); // add your sensor
uint32_t rgb = mcp.map2RGB(pressure);
Serial.print("P: ");
Serial.println(rgb, HEX); // replace with PWM-RGB led
delay(1000);
}
// -- END OF FILE --

View File

@ -0,0 +1,89 @@
//
// FILE: map2colour_temperature.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: map2colour demo
// DATE: 2021-12-04
// URL: https://github.com/RobTillaart/map2colour
// demo simulates a temperature sensor and its mapping upon colours
// temp -20, 5, 10, 30, 35, 50, 200
// Red yellow black black yellow red red
// note thart the middle area 10..30 has no colour.
#include "Arduino.h"
#include "map2colour.h"
map2colour mct;
map2colour mch;
// should be in increasing order; and 7 elements
// temperature
float Tvalues[7] = { -20, 5, 10, 30, 35, 50, 200 };
uint32_t Tcolours[7] =
{
0x00FF0000, 0x00FFFF00, 0x00000000,
0x00000000, 0x00FFFF00, 0x00FF0000,
0x00FF0000
};
// humidity around 35 is perfect
float Hvalues[7] = { 0, 20, 30, 35, 40, 50, 100 };
uint32_t Hcolours[7] =
{
M2C_RED, M2C_RED, M2C_YELLOW,
M2C_LIME, M2C_YELLOW, M2C_RED,
M2C_RED
};
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
mct.begin(Tvalues, Tcolours);
mch.begin(Hvalues, Hcolours);
for (int i = -20; i < 60; i++)
{
uint32_t rgb = mct.map2RGB(i);
Serial.print(i);
Serial.print("\t");
Serial.println(rgb, HEX);
}
Serial.println();
for (int i = 20; i < 50; i++)
{
uint32_t rgb = mch.map2RGB(i);
Serial.print(i);
Serial.print("\t");
Serial.println(rgb, HEX);
}
Serial.println();
}
void loop()
{
float temperature = analogRead(A0)/10; // add your sensor
uint32_t rgb = mct.map2RGB(temperature);
Serial.print("T: ");
Serial.print(rgb, HEX); // replace with PWM-RGB led
Serial.print("\t\t");
float humidity = analogRead(A1)/10; // add your sensor
rgb = mch.map2RGB(humidity);
Serial.print("H: ");
Serial.println(rgb, HEX); // replace with PWM-RGB led
delay(1000);
}
// -- END OF FILE --

View File

@ -5,11 +5,29 @@ map2colour KEYWORD1
# Methods and Functions (KEYWORD2)
KEYWORD2
KEYWORD2
begin KEYWORD2
map2RGB KEYWORD2
map2_565 KEYWORD2
# Constants (LITERAL1)
MAP2COLOUR_LIB_VERSION LITERAL1
M2C_BLACK LITERAL1
M2C_SILVER LITERAL1
M2C_GRAY LITERAL1
M2C_WHITE LITERAL1
M2C_MAROON LITERAL1
M2C_RED LITERAL1
M2C_PURPLE LITERAL1
M2C_FUCHSIA LITERAL1
M2C_GREEN LITERAL1
M2C_LIME LITERAL1
M2C_OLIVE LITERAL1
M2C_YELLOW LITERAL1
M2C_NAVY LITERAL1
M2C_BLUE LITERAL1
M2C_TEAL LITERAL1
M2C_AQUA LITERAL1

View File

@ -1,6 +1,6 @@
{
"name": "map2colour",
"keywords": "",
"keywords": "color, colour, map, RGB, 565",
"description": "Arduino library for mapping a float to colour spectrum.",
"authors":
[
@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/map2colour.git"
},
"version": "0.1.0",
"version": "0.1.4",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,9 +1,9 @@
name=map2colour
version=0.1.0
version=0.1.4
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for mapping a float to colour spectrum
paragraph=
paragraph=supports 24 bit RGB and 16 bit 565 format.
category=Data Processing
url=https://github.com/RobTillaart/map2colour
architectures=*

View File

@ -1,12 +1,20 @@
//
// FILE: map2colour.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// VERSION: 0.1.4
// PURPOSE: Arduino library for mapping a float to colour spectrum
// URL: https://github.com/RobTillaart/map2colour
//
// HISTORY:
// 0.1.0 2021-12-04 initial version
// 0.1.0 2021-12-04 initial version.
// 0.1.1 2021-12-05 add user defined colour-map.
// add unit tests, update readme.md.
// 0.1.2 2021-12-06 add map2_565(),
// add + improve examples.
// fix value > upper bug
// 0.1.3 2021-12-07 improve performance map2RGB
// 0.1.4 2021-12-08 add derived class that is fast and uses more MEMORY / RAM
//
#include "map2colour.h"
@ -17,9 +25,28 @@ map2colour::map2colour()
}
bool map2colour::begin(float * values)
bool map2colour::begin(float * values, uint32_t * colourMap)
{
// split colour map in channels
if (colourMap != NULL)
{
for (int i = 0; i < 7; i++)
{
uint32_t val = colourMap[i];
_Blue[i] = val & 0xFF;
val >>= 8;
_Green[i] = val & 0xFF;
val >>= 8;
_Red[i] = val & 0xFF;
}
}
_values = values;
for (int index = 1; index < 7; index++)
{
// catch non increasing values.
float den = _values[index] - _values[index - 1];
if (den <= 0.0) return false;
}
return true;
}
@ -27,18 +54,43 @@ bool map2colour::begin(float * values)
uint32_t map2colour::map2RGB(float value)
{
int index = 1;
float factor = 0;
// default values + out of lower range
uint8_t R = _Red[0];
uint8_t G = _Green[0];
uint8_t B = _Blue[0];
if ( (_values[0] < value) && (value <= _values[6] ))
if (_values[0] < value)
{
while ((index < 7) && (_values[index] < value)) index++;
factor = 1 - (_values[index] - value) / (_values[index] - _values[index-1]);
R = _Red[index - 1] + factor * (_Red[index] - _Red[index - 1]);
G = _Green[index - 1] + factor * (_Green[index] - _Green[index - 1]);
B = _Blue[index - 1] + factor * (_Blue[index] - _Blue[index - 1]);
if (value <= _values[6] )
{
// search the interval
while (_values[index] < value) index++;
// base value
R = _Red[index];
G = _Green[index];
B = _Blue[index];
// calculate the interpolation factor
// OPTIMIZE USE PRECALCULATED DIVIDERS (costs 24 bytes extra RAM).
float factor = (_values[index] - value) / (_values[index] - _values[index - 1]);
// interpolate if delta <> 0
int delta = _Red[index] - _Red[index - 1];
if (delta != 0 ) R -= factor * delta;
delta = _Green[index] - _Green[index - 1];
if (delta != 0 ) G -= factor * delta;
delta = _Blue[index] - _Blue[index - 1];
if (delta != 0 ) B -= factor * delta;
}
else
{
// out of upper range
R = _Red[6];
G = _Green[6];
B = _Blue[6];
}
}
uint32_t colour = R;
colour <<= 8;
@ -49,5 +101,107 @@ uint32_t map2colour::map2RGB(float value)
}
uint16_t map2colour::map2_565(float value)
{
uint32_t RGB = map2RGB(value);
uint16_t colour = 0x0000;
RGB >>= 3;
colour |= (RGB & 0x001F); // B channel 5 bits
RGB >>= 2;
colour |= (RGB & 0x07E0); // G channel 6 bits
RGB >>= 3;
colour |= (RGB & 0xF800); // R channel 5 bits
return colour;
}
/////////////////////////////////////////////////////////////////////////
//
// DERIVED CLASS
//
map2colourFast::map2colourFast() : map2colour()
{
}
bool map2colourFast::begin(float * values, uint32_t * colourMap)
{
if (map2colour::begin(values, colourMap) == false)
{
return false; // non increasing values.
}
// calculate dividers
for (int index = 1; index < 7; index++)
{
divFactor[index - 1] = 1.0 / (_values[index] - _values[index - 1]);
}
return true;
}
uint32_t map2colourFast::map2RGB(float value)
{
int index = 1;
// default values + out of lower range
uint8_t R = _Red[0];
uint8_t G = _Green[0];
uint8_t B = _Blue[0];
if (_values[0] < value)
{
if (value <= _values[6] )
{
// search the interval
while (_values[index] < value) index++;
// base value
R = _Red[index];
G = _Green[index];
B = _Blue[index];
// calculate the interpolation factor
float factor = (_values[index] - value) * divFactor[index - 1];
// interpolate if delta <> 0
int delta = _Red[index] - _Red[index - 1];
if (delta != 0 ) R -= factor * delta;
delta = _Green[index] - _Green[index - 1];
if (delta != 0 ) G -= factor * delta;
delta = _Blue[index] - _Blue[index - 1];
if (delta != 0 ) B -= factor * delta;
}
else
{
// out of upper range
R = _Red[6];
G = _Green[6];
B = _Blue[6];
}
}
uint32_t colour = R;
colour <<= 8;
colour |= G;
colour <<= 8;
colour |= B;
return colour;
}
uint16_t map2colourFast::map2_565(float value)
{
uint32_t RGB = map2RGB(value);
uint16_t colour = 0x0000;
RGB >>= 3;
colour |= (RGB & 0x001F); // B channel 5 bits
RGB >>= 2;
colour |= (RGB & 0x07E0); // G channel 6 bits
RGB >>= 3;
colour |= (RGB & 0xF800); // R channel 5 bits
return colour;
}
// -- END OF FILE --

View File

@ -2,7 +2,7 @@
//
// FILE: map2colour.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// VERSION: 0.1.4
// PURPOSE: Arduino library for mapping a float to colour spectrum
// URL: https://github.com/RobTillaart/map2colour
//
@ -10,7 +10,26 @@
#include "Arduino.h"
#define MAP2COLOUR_LIB_VERSION (F("0.1.0"))
#define MAP2COLOUR_LIB_VERSION (F("0.1.4"))
// https://www.w3.org/wiki/CSS/Properties/color/keywords
#define M2C_BLACK 0x00000000
#define M2C_SILVER 0x00C0C0C0
#define M2C_GRAY 0x00808080
#define M2C_WHITE 0x00FFFFFF
#define M2C_MAROON 0x00800000
#define M2C_RED 0x00FF0000
#define M2C_PURPLE 0x00800080
#define M2C_FUCHSIA 0x00FF00FF
#define M2C_GREEN 0x00008000
#define M2C_LIME 0x000FF000
#define M2C_OLIVE 0x00808000
#define M2C_YELLOW 0x00FFFF00
#define M2C_NAVY 0x00000080
#define M2C_BLUE 0x000000FF
#define M2C_TEAL 0x00008080
#define M2C_AQUA 0x0000FFFF
class map2colour
@ -18,20 +37,40 @@ class map2colour
public:
map2colour();
// values is an array of 7 values
bool begin(float * values);
// values is an array of 7 values in ascending order
bool begin(float * values, uint32_t * colourMap = NULL);
uint32_t map2RGB(float value);
uint16_t map2_565(float value);
private:
protected:
uint8_t _size = 7;
float * _values;
// default colours, split up per channel for performance.
uint8_t _Red[7] = { 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF };
uint8_t _Green[7] = { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF };
uint8_t _Blue[7] = { 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF };
};
/////////////////////////////////////////////////////////////////////////
//
// DERIVED CLASS
//
// FASTER + MORE RAM
//
class map2colourFast : public map2colour
{
public:
map2colourFast();
// values is an array of 7 values in ascending order
bool begin(float * values, uint32_t * colourMap = NULL);
uint32_t map2RGB(float value);
uint16_t map2_565(float value);
private:
float divFactor[6];
};
// -- END OF FILE --

View File

@ -35,12 +35,71 @@ unittest_teardown()
}
unittest(test_constructor)
unittest(test_constructor_I)
{
fprintf(stderr, "MAP2COLOUR_LIB_VERSION: %s\n", (char *) MAP2COLOUR_LIB_VERSION);
map2colour mc;
float values[7] = { 1, 2, 3, 4, 5, 6, 7 };
assertTrue(mc.begin(values));
assertEqual(0x00000000, mc.map2RGB(1));
assertEqual(0x00FF0000, mc.map2RGB(2));
assertEqual(0x00FFFF00, mc.map2RGB(3));
assertEqual(0x0000FF00, mc.map2RGB(4));
assertEqual(0x0000FFFF, mc.map2RGB(5));
assertEqual(0x000000FF, mc.map2RGB(6));
assertEqual(0x00FFFFFF, mc.map2RGB(7));
}
unittest(test_constructor_II)
{
fprintf(stderr, "MAP2COLOUR_LIB_VERSION: %s\n", (char *) MAP2COLOUR_LIB_VERSION);
map2colour mc;
float values[7] = { 1, 2, 3, 4, 5, 6, 7 };
uint32_t colours[7] =
{
M2C_WHITE, M2C_BLACK, M2C_FUCHSIA, M2C_OLIVE, M2C_NAVY, M2C_GREEN, M2C_YELLOW
};
assertTrue(mc.begin(values, colours));
assertEqual(M2C_WHITE, mc.map2RGB(1));
assertEqual(M2C_BLACK, mc.map2RGB(2));
assertEqual(M2C_FUCHSIA, mc.map2RGB(3));
assertEqual(M2C_OLIVE, mc.map2RGB(4));
assertEqual(M2C_NAVY, mc.map2RGB(5));
assertEqual(M2C_GREEN, mc.map2RGB(6));
assertEqual(M2C_YELLOW, mc.map2RGB(7));
}
unittest(test_constants)
{
fprintf(stderr, "MAP2COLOUR_LIB_VERSION: %s\n", (char *) MAP2COLOUR_LIB_VERSION);
assertEqual(M2C_BLACK ,0x00000000);
assertEqual(M2C_SILVER ,0x00C0C0C0);
assertEqual(M2C_GRAY ,0x00808080);
assertEqual(M2C_WHITE ,0x00FFFFFF);
assertEqual(M2C_MAROON ,0x00800000);
assertEqual(M2C_RED ,0x00FF0000);
assertEqual(M2C_PURPLE ,0x00800080);
assertEqual(M2C_FUCHSIA ,0x00FF00FF);
assertEqual(M2C_GREEN ,0x00008000);
assertEqual(M2C_LIME ,0x000FF000);
assertEqual(M2C_OLIVE ,0x00808000);
assertEqual(M2C_YELLOW ,0x00FFFF00);
assertEqual(M2C_NAVY ,0x00000080);
assertEqual(M2C_BLUE ,0x000000FF);
assertEqual(M2C_TEAL ,0x00008080);
assertEqual(M2C_AQUA ,0x0000FFFF);
}
unittest_main()