如何提高arduino TMP36温度读数?

时间:2017-08-30 09:09:23

标签: c++ performance arduino floating-point sensor

Arduino love-o-meter项目(存在于入门套件中)使用float来计算从TMP36读取的电压的温度。

Arduino Uno微控制器(ATmega328P)没有任何FPU,并且计算没有良好的性能。

我们如何改进这项计算?

// Code for 5V at the input of the TMP36
int reading = analogRead(PIN);
float voltage = (reading * 500.0) / 1024.0;  
float celciusTemperature = voltage - 50.0; 

1 个答案:

答案 0 :(得分:0)

性能不佳的原因是使用浮点值。

我将展示如何摆脱它。

首先我们谈谈精确度:

  • TMP36的温度范围为500°C(-50°C至+ 450°C)。
  • 模拟读取工作在0到1023之间的10位(1024个可能的值)。

因此精度为500/1024。大约0.5°C。

因此,如果我们想在int上编码温度,则int的较低有效位需要编码为0.5°C而不是1°C。

示例:

int celciusTemperatureByHalfDegree = +40; // +20.0°C
int celciusTemperatureByHalfDegree = +41; // +20.5°C
int celciusTemperatureByHalfDegree = -10; // -5.0°C
int celciusTemperatureByHalfDegree = -15; // -5.5°C

我们看到了:

celciusTemperatureByHalfDegree = celciusTemperature * 2

大致会有:

int reading = analogRead(PIN);
int voltage = (reading * 500) / 1024;  
int celciusTemperature = voltage - 50;
int celciusTemperatureByHalfDegree = celciusTemperature * 2;

此时溢出和舍入问题导致此代码无效。

让我们简化一下:

int reading = (analogRead(PIN) * 500) / 1024;
int celciusTemperatureByHalfDegree = (reading - 50) * 2;

再次:

int reading = (analogRead(PIN) * 500) / 512;
int celciusTemperatureByHalfDegree = reading - 100;

再次:

int reading = (analogRead(PIN) * 125) / 128;
int celciusTemperatureByHalfDegree = reading - 100;

此时不存在舍入问题。但是analogRead()给出了0到1023之间的输出。

1023 * 125大于最大int16(32,767),因此可能出现溢出。

这里我们将使用125 = 5 * 25和128 = 4 * 32。

int reading = (analogRead(PIN) * 5 * 25) / (4 * 32);
int celciusTemperatureByHalfDegree = reading - 100;

将成为:

int reading = analogRead(PIN); // 0 to 1023
reading *= 5;                  // 0 to 5115 (no overflow)
reading /= 4;                  // 0 to 1278 (no overflow)
reading *= 25;                 // 0 to 31950 (no overflow)
reading /= 32;                 // 0 to 998
int celciusTemperatureByHalfDegree = reading - 100;

最后要打印它,我们将使用此代码:

// print the integer value of the temperature
Serial.print(celciusTemperatureByHalfDegree/2);
Serial.print(".");
// less significant bit code for "__.0" of "__.5"
Serial.print(celciusTemperatureByHalfDegree % 2 ? '5' : '0'); 
Serial.print("°C");