Normalizar un valor entre 0 y 1en Arduino.

Cuando quieres comparar distintos datos en distintos rangos es habitual el tener que normalizarlos entre 0 y 1, es decir, convertir una variable de un rango de valores [in_min, in_max] a otro que va de 0 a 1. Para ello podemos usar la función map.

map(x, in_min, in_max, 0.0, 1.0);

En esta otra entrada de blog hay más información sobre la función map y como optimizarla, vamos a usar esos trucos para crear funciones de normalización más optimas.

Lo primero es que como los valores sobre los que se «mapea» son siempre los mismos 0 y 1 podemos crear nuestra propia función a partir del código de la función map.

long map(long x, long in_min, long in_max, long out_min, long out_max) {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Se reemplaza out_min por 0 y out_max por 1 y se simplifican los cálculos:

long map(long x, long in_min, long in_max, long out_min, long out_max) {
    return (x - in_min) * (1 - 0) / (in_max - in_min) + 0;
}

Obteniendo:

long normalize(long x, long in_min, long in_max) {
    return (x - in_min) / (in_max - in_min);
}

Vamos a crear también funciones para los float y los double:

float floatNormalize(float x, float in_min, float in_max) {
    return (x - in_min) / (in_max - in_min);
}

double doubleNormalize(double x, double in_min, double in_max) {
    return (x - in_min) / (in_max - in_min);
}

Genial, pero aun podemos hacer otra mejora, la función anterior es genérica, si vamos a aplicar la normalización siempre a valores en el mismo rango podemos crear una nueva función donde remplacemos in_min e in_max por los valores de este rango. Por ejemplo en un rango de 0 a 1023:

//in: 0..1023
//in_min = 0
//in_max = 1023

long customNormalize(long x){
    return (x - 0) / (1023 - 0);
}

Simplificando:

long customNormalize(long x){
    return x / 1023;
}

Hemos reducido el coste de la normalización a una solo división, en el peor de los casos (cuando el in_min no sea 0) será una resta y una división.