Modificar datos de las entradas analógicas

Buenas:

En este ejemplo, tengo dos potenciómetros conectados a Arduino UNO r3.

int valorPot1 = 0;
int valorPot2 = 0;

void setup()
{
  // Configurado 9600 baudios.
  Serial.begin(9600); // 115200.
  
  // Configurar entradas analogicas.
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
}

void loop()
{
  // Lee valores entradas analógicas 
  // y lo almacena en las variables.
  valorPot1 = analogRead(A1);
  valorPot2 = analogRead(A2);

  // Envía valores al puerto serie.
  Serial.print(valorPot1);
  Serial.print(",");
  Serial.println(valorPot2);

  // Retardo de 1 segundo.
  delay(1000); // 1000 mili segundos o 1 segundo.
}

En cada potenciómetro envía valores de 0 a 1023.

Quiero hacer dos cosas.

Potenciómetro 1 o el A1, quiero que envía exactamente de 0 a 100.
Con el A2, quiero que el rango del potenciómetro sea del 90 al -90.

Me he vuelto loco y no me sale resultados deseados.

¿Es posible hacerlo realmente?

Salududos.

Sencillo

Pote1 = map(lectura1, 0, 1023, 0, 100);
Pote2 = map(lectura2, 0, 1023, 90, -90);

Saludos

Perdón por mi comentario pero si alguien se sienta frente a una computadora es porque tiene cierto nivel de estudios.
Quien no sabe lo que es la regla de 3 simple?
Supongo que todos la aprendimos en la escuela primaria sea el lugar del mundo donde habitemos

Entonces porque no pensar un poco?

si 1023 ----------- 100
lectura1 ------ x = lectura1*100/1023

Veamos si funciona? Si el potenciometro esta a la mitad serán 512 cuentas del ADC

x = 512 * 100/1023 = aprox a 50

Si fueran 127 o sea 1/4 entonces da 25

con lo que funciona

Ahora vamos a la secundaria. Matemática de 2 o 3 año. Ecuación de la recta.
Una recta se define como y = m*x + b
Donde m pendiente
b ordenada al origen
x dato
y lo que queremos obtener

b o sea l aordenada al origen enel 2do caso es -90
m la pendiente es m = (y2-y1)/(x2-x1) = (90 -(-90))/(1023-0) = 180/1023

m = 180/1023
b = -90
y = 180/1023 *x - 90

Esta escuación describe cualquier punto del segundo caso.
Claro que tal vez no muchos se acuerden

Entonces veamos que pasa para x = 512 o sea la mitad entre -90 y 90 que intuitivamamente sabemos debe dar 0

y = 180/1023*512 -90 = 90 - 90 = 0 comprobado

Asi con cualquier otro punto.

Por supuesto map resume todo esto porque es precisamente lo que acabo de escribir para la ecuación de la recta.

Muchísimas gracias a los dos compañeros.

Hola de nuevo:

He probado con el map.

nivelAgua = map(valorPot2, 0, 1023, 90, -90);

Funciona de maravilla.

Lo he intentado hacer directamente así, pero no me sale, es más, no se hacerlo de forma correcta.

nivelAgua = valorPot2 * (-90.0 / 1023.0);

Dejo el código completo.

// Include el código de la librería.
#include <LiquidCrystal.h>

// Inicializa la librería con sus pines indicados.
// RS, RW, Enable, D4, D5, D6, D7.
//LiquidCrystal lcd(8, NULL, 9, 4, 5, 6, 7);
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// Pin 10 para saber que es luz de fondo.
// const byte LuzFondo = 10;

const byte pinA1 = A1;
const byte pinA2 = A2;
int valorPot1 = 0;
float velocidadMotor = 0;
int valorPot2 = 0;
float nivelAgua = 0;

void setup()
{
  // Baudios.
  Serial.begin(115200);

  // La pantalla es de 16 caracteres y 2 filas.
  lcd.begin(16, 2);

  // Indicar luz de fondo como salida.
  // pinMode(LuzFondo, OUTPUT);

  // Configurar entradas analógicas.
  pinMode(pinA1, INPUT);
  pinMode(pinA2, INPUT);
}

void loop()
{
  valorPot1 = analogRead(pinA1);
  valorPot2 = analogRead(pinA2);

  velocidadMotor = valorPot1 * (100.0 / 1023.0);
  //nivelAgua = valorPot2 * (-90.0 / 1023.0);
  
  nivelAgua = map(valorPot2, 0, 1023, 90, -90);

  // Mostrar datos en el LCD.
  // Línea 1 del LCD velocidad del motor a 0 a 100.
  lcd.setCursor(0, 0);
  lcd.print(F("Velocidad: "));
  lcd.setCursor(12, 0);
  lcd.print(F("    "));
  lcd.setCursor(12, 0);
  lcd.print(velocidadMotor);

  // Línea 2 del LCD nivel del agua de 90 a -90.
  lcd.setCursor(0, 1);
  lcd.print(F("Nivel agua: "));
  lcd.setCursor(12, 1);
  lcd.print(F("    "));
  lcd.setCursor(12, 1);
  lcd.print(nivelAgua);

  // Enviar datos al puerto serie.
  Serial.print(velocidadMotor);
  Serial.print(",");
  Serial.println(nivelAgua);
  delay(500); // 500 mili segundos o 0.5 segundos..
}

Con el map si muestra bien los valores, a mi manera que lo quiero sin map, no me sale.

nivelAgua = valorPot2 / 1023.0 * (-180) + 90;

Saludos

@gatul

¡¡¡Funciona!!!

Por fin.

He estado intentando mirar la función pero no lo encuentro en los archivos de Arduino IDE como es, pero aquí está el 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;
}

Quería saber sobre sus fórmulas como explicó arriba el compañero, lo que no entendía mucho.

Más que nada, quiero saber si puedo hacer una función en el cual me muestre decimales, que el map normal no lo hace.

Un ejemplo tonto, se puede crear un map2 por llamarlo de alguna manera que funcione con decimales con float, un ejemplo.

  int valorPot3 = 723;
  // Función map2 con decimales.
  float map2(float x, float in_min, float in_max, float out_min, float out_max)
  {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
  }

  float velocidadMotor2 = map2(valorPot3, 0.0, 1023.0, 0.0, 100.0);

Dejo el ejemplo gracias a los dos por si alguien lo necesita.

// Include el código de la librería.
#include <LiquidCrystal.h>

// Inicializa la librería con sus pines indicados.
// RS, RW, Enable, D4, D5, D6, D7.
//LiquidCrystal lcd(8, NULL, 9, 4, 5, 6, 7);
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// Pin 10 para saber que es luz de fondo.
// const byte LuzFondo = 10;

const byte pinA1 = A1;
const byte pinA2 = A2;
int valorPot1 = 0;
float velocidadMotor = 0;
int valorPot2 = 0;
float nivelAgua = 0;

void setup()
{
  // Baudios.
  Serial.begin(115200);

  // La pantalla es de 16 caracteres y 2 filas.
  lcd.begin(16, 2);

  // Indicar luz de fondo como salida.
  // pinMode(LuzFondo, OUTPUT);

  // Configurar entradas analógicas.
  pinMode(pinA1, INPUT);
  pinMode(pinA2, INPUT);
}

void loop()
{
  valorPot1 = analogRead(pinA1);
  valorPot2 = analogRead(pinA2);

  // Cálculo convencional.
  velocidadMotor = valorPot1 * (100.0 / 1023.0);
  nivelAgua = valorPot2 / 1023.0 * (-180) + 90;

  // Cálculo con map.
  //velocidadMotor = map(valorPot1, 0, 1023, 0, 100);
  //nivelAgua = map(valorPot2, 0, 1023, 90, -90);

  // Mostrar datos en el LCD.
  // Línea 1 del LCD velocidad del motor a 0 a 100.
  lcd.setCursor(0, 0);
  lcd.print(F("Velocidad: "));
  lcd.setCursor(11, 0);
  lcd.print(F("    "));
  lcd.setCursor(11, 0);
  lcd.print(velocidadMotor);

  // Línea 2 del LCD nivel del agua de 90 a -90.
  lcd.setCursor(0, 1);
  lcd.print(F("Nivel agua: "));
  lcd.setCursor(11, 1);
  lcd.print(F("    "));
  lcd.setCursor(11, 1);
  lcd.print(nivelAgua);

  // Enviar datos al puerto serie.
  Serial.print(velocidadMotor);
  Serial.print(",");
  Serial.println(nivelAgua);
  delay(500); // 500 mili segundos o 0.5 segundos..
}

Saludos camaradas.

La función map, según está implementada en Arduino, no es exacta, o no funciona como al menos yo esperaría que funcionase.
Funcionaría perfectamente si estuviesemos trabajando con números reales, pero como trabajamos con números enteros debido a la digitalización, es bastante imprecisa en mi opinión.
Si alguien tiene dudas sobre lo que digo, que intente convertir los 0 a 1023 valores de entrada a un rango de 0 a 1 y se sorprenderá del resultado: No salen un 50% de valores 0 y un 50% de valores 1, como ocurriría si fuesen números reales y yo esperaría. Salen 1023 valores con 0 y solo uno con un 1.
Para corregirlo habría que sumar 1 a los dos valores máximos de la función. Solo a los máximos, y no a los mínimos, ni al valor original.

Si hablas de números enteros la respuesta es precisa en ese conjunto numérico.
Convertir 0 a 1023 en un rango 0 a 1 tiene que otra solución para ti?
Seguramente esperarías que todo lo que este por debajo de 512 debería dar 0 y lo que este por encima 1. Pues no es el caso. Solo 1023 da 1 y todo lo demas da 0.

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;
}

Si y = (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
donde :
out_min = 0
out_max = 1
in_min = 0
in_max = 1023
entonces en el campo de los Números enteros hablamos de los Naturales positivos, el cero y los opuestos o negativos. En este conjunto matemático no hay coma decimal. Asi que las cosas son 0, 1, 2,… n o sus opuestos
0.555 no existe, es 0 y 0.999999 no existe es 0 tmb
Ahora si tu quieres redondear con +0.5 (en reales o float) es otra cosa y ahi aparecen otros resultados.
Si haces la formula con enteros usando Excel el único número que da 1 es 1023 y esta CORRECTO.
Pero si haces una fórmula con floats (reales), entonces aparecen todo tipo de números intermedios y es CORRECTO porque hablamos de otro conjunto numérico, así que no existe tal imprecisión.
Hay creo yo, una mala interpretación de tu parte en este caso, algo que me ocurre a mi también en otros casos.

Hola Surbyte,

encantado de saludarte.

1.- Estoy TOTALMENTE de acuerdo con que la función MAP de Arduino cuando la ejecutas para “relacionar” los rangos de números enteros 0-1023 a 0-1, siguiendo sus propias instrucciones, da como resultado 0 para los valores 0 a 1022 y 1 para el valor 1023.
La fórmula de la función map hace precisamente eso:

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;
}

2.- Pero si quieres “relacionar” los dos rangos de números enteros para que den resultados más … “distribuidos”, como por ejemplo que al relacionar los rangos de números enteros 0-1023 a 0-1, dé como resultado 0 para los valores 0-511, y 1 para valores de 512 a 1023, la función map no sirve tal y como está indicada.
Para ello, deberías hacer una regla de tres, multiplicar el valor original por 2 y dividir por 1024 (y truncar los decimales).

(x - 0) * (2 - 0) / (1024 - 0) + 0

3,. No conozco ningún fenómeno físico, ni ningún razonamiento matemático común por el que interese tener un resultado de la relación entre rangos de números enteros como el que da la función map de Arduino.
No descarto que no lo haya, pero ahora mismo no caigo, y eso que mi background es técnico-científico.
Lo que sí conozco son muchos fenómenos físicos y teoremas matemáticos en el que una relación más “distribuida” es necesaria.

  1. Pero si se usa la función map de Arduino tal y como está, pero poniendo en los valores max, el valor máximo de cada rango a “relacionar” sumando 1, el resultado es justamente el “distribuido”.

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

Si a alguien le sirve, perfecto.

Las cosas a veces se hacen para resolver necesidades mas simples. Algo como pasar relacionar 0-1023 y tener una respuesta 0-1 no me resulta muy interesante.
Algo como convertir 0-1023 en 8 16 32 o mas pasos si solo por dar un ejemplo simple.

Te entiendo pero yo no reniego contra estas cosas. Lo que hago es como lo que tu mismo has deducido, una una función mapfloat y asunto terminado y si quiero la modifico a mi gusto.

Según tu punto de vista que debería hacer map o una función similar porque estamos los dos de acuerdo pero no se en qué estamos de acuerdo? Bueno, si lo sé, estamos de acuerdo en que map entera es por lo menos limitada pero como digo es un punto de vista.

Si tengo un potenciometro y se me ocurre como he respondido en el foro manejar un menú LCD (algo que no me cuadra pero como dije he visto muchos hilos con esta idea) la función trabaja bien.
Otro ejemplo es el de convertir la lectura analógica de un sensor en valores 0-100% y otra es hacerlo en valores tipo offeset y fondo de escala, pero acá coincidiremos que me resulta mas práctica una función real o con float.

Moderador:
Por cierto cuando pongas aunque solo sea una línea de código que sea con etiquetas por favor.
Tienes en tu post anterior dos funciones map donde no lo has hecho.

Muchas gracias Surbyte.

Veo que coincidimos en muchas cosas.

Con respecto a la “sugerencia”, lo siento de verdad, no lo sabía y en verdad no sé como se hace lo de las etiquetas.
Nota: he estado buscando las instrucciones que debería haber leído previamente, y no las he encontrado.
Me puedes indicar dónde buscar, por favor.

Un cordial saludo.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.