2017-08-30 3 views
-1

Le projet Arduino love-o-meter (présent dans le kit de démarrage) utilise un float pour calculer la température à partir de la tension lue sur le TMP36.Comment améliorer une lecture de température arduino TMP36?

Le microcontrôleur Arduino Uno (ATmega328P) n'a aucun FPU et le calcul n'a pas de bonnes performances.

Comment pouvons-nous améliorer ce calcul?

// 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; 
+0

Je pense qu'il serait plus utile de remplacer la balise [précision] avec une langue marque. –

Répondre

0

La cause des mauvaises performances est l'utilisation de valeurs à virgule flottante.

Je vais montrer comment m'en débarrasser.

D'abord nous parler de précision:

  • Le TMP36 a une portée de 500 ° C (de -50 ° C à + 450 ° C).
  • La lecture analogique fonctionne sur 10 bits de 0 à 1023 (1024 valeurs possibles).

La précision est donc de 500/1024. Environ 0,5 ° C.

Donc, si nous voulons coder la température sur un int, le bit moins significatif de ce int doit coder pour 0,5 ° C au lieu de 1 ° C.

Exemple:

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

On voit que:

celciusTemperatureByHalfDegree = celciusTemperature * 2 

Environ aura:

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

A ce stade, un trop-plein et les problèmes d'arrondi font que ce code soit inutile.

Simplifions il:

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

Et encore:

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

Et encore:

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

A ce stade, il n'y a pas de problème plus arrondi. Mais analogRead() donne une sortie entre 0 et 1023.

Et 1023 * 125 est plus grand que max int16 (32767), si le dépassement est possible.

Ici, nous allons utiliser 125 = 5 * 25 et 128 = 4 * 32.

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

deuiendront:

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; 

Enfin, pour l'imprimer nous utiliserons ce code:

// 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");