Как вернуть значение из нецелочисленного ввода между 0-5 из диапазона вывода 0-320 в методе map()

Я экспериментирую с использованием метода map() в скетче ArduinoIDE, пытаясь получить положение пикселя для горизонтального измерителя в диапазоне 0–320 из входного значения в диапазоне 0–5. Однако, когда я это делаю, я вижу в методе, что ввод должен быть «длинным». Вот мой пример кода:

  float voltage = 2.5;
  float meterPosition = map(voltage, 0, 5, 0, 320);
  tft.fillRect(0, 0, meterPosition, 10, TFT_GREEN);
  tft.setCursor(10, 70);
  tft.setTextSize(3);
  tft.println(voltage);
  tft.println(meterPosition);

Но когда я запускаю это, несмотря на то, что входное значение составляет 50% входного диапазона, я ожидал, что значениеmeterPosition будет 160, но оно равно 128, я думаю, из-за того, что значения для этого метода должны быть типа 'long ' и поэтому значение 'float' округляется и становится типом 'long' (думаю, именно это и происходит!!).

Меня смущает функция метода map(), если вы не можете сопоставить какой-либо диапазон с любым другим диапазоном без использования десятичных знаков в качестве входных данных. Я явно что-то здесь упускаю, так что же мне нужно изменить в коде метода map(), чтобы он работал в моем примере, пожалуйста, если я не могу использовать числа с плавающей запятой ?

Спасибо. Джон

, 👍0

Обсуждение

Как насчет того, чтобы просто сказать «floatmeterPosition = voltage * 64.0;»?, @6v6gt


2 ответа


Лучший ответ:

1

Как вы уже заметили, функция 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;
}

Если вы хотите использовать числа с плавающей запятой, вы можете написать версию этой функции. который работает с float. Обратите внимание, однако, что, поскольку вы используете нули как для in_min, так и для out_min выражение упрощается до становится тривиальным:

float meterPosition = voltage * 320 / 5.0;

Однако я бы предложил два небольших изменения в этом выражении:

  • добавьте скобки вокруг (320 / 5.0): тогда это соотношение будет оценивается во время компиляции, и вы сэкономите дорогостоящее время выполнения деление с плавающей запятой

  • округлить до ближайшего целого числа, чтобы свести к минимуму ошибку: ваш позиция пикселя в любом случае должна быть целым числом.

С этими предложениями у нас есть:

int meterPosition = round(voltage * (320 / 5.0));

Не забывайте .0 в 5.0, иначе вы получите целое число подразделение.

Обратите внимание, что использование map() с диапазонами, масштабированными с коэффициентом 100, не является ужасно хорошая идея: вы потратите довольно много циклов процессора, выполняя бесполезные вычисления, а результат будет испорчен двумя округлениями ошибки вместо одной.

,

0

Извините за мою глупость! Я думаю, что понял, как это сделать, это просто вопрос масштабирования входных значений и диапазона ввода на 100.

,