DS18B20温度センサが浮動小数点関数として返って、時間の50%を返す

私はちょうどDS18B20温度センサーを持っており、代わりに関数を使用するようにサンプルコードを修正しようとしています。以下は私の getTemp 関数です。それは動作しているが、時間の0の部分で結果を返す例:

温度= 72.39
  温度= 0.00

関数内に Serial.print(fahrenheit); を追加すると、常に正しい温度が提供されます。私はこれが遅延を必要とするかもしれないが、私のループに delay(5000); を追加することは役に立たなかったかもしれませんが。

私はそれが単純なものであると仮定していますが、 float がどのように復帰するかを理解していません。

#include 

// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

OneWire  ds(2); //on pin 10 (a 4.7K resistor is necessary)

void setup(void) {
  Serial.begin(9600);
}

float getTemp(char tScale) {
  byte i;
  byte present = 0;
  byte type_s = 0;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;

  if ( !ds.search(addr)) {
    ds.reset_search();
    delay(250);
    return false;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);       //start conversion, with parasite power on at the end

  delay(1000);    //maybe 750ms is enough, maybe not
 //we might do a ds.depower() here, but the reset will take care of it.

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE);        //Read Scratchpad

  for ( i = 0; i < 9; i++) {          //we need 9 bytes
    data[i] = ds.read();

  }

 //Convert the data to actual temperature
 //because the result is a 16 bit signed integer, it should
 //be stored to an "int16_t" type, which is always 16 bits
 //even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3;//9 bit resolution default
    if (data[7] == 0x10) {
     //"count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
   //at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7; //9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3;//10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1;//11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw/16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  if (tScale == 'C') {
    return celsius;
  }
  else if (tScale == 'F') {
    return fahrenheit;
  }

}
void loop(void) {
    Serial.print("Temperature = ");
    Serial.println( getTemp( 'F' ) );


}

編集: 面白いことに、 if ステートメントをループに追加すると、これが修正されます。私はまだ何が起こっているのか理解したいと思います:

void loop(void) {
  if ( getTemp( 'F' ) == 0 ){
    Serial.print( "Temperature = " );
    Serial.println( getTemp( 'F' ) );
  }
}
0
追加された 編集された
ビュー: 1
明らかに、出版された仕様のタイミングに合致しない市場で「DS18B20」と主張されているデバイスがたくさんあります。それらを使用しようとすると、物事を遅くする必要があります。下位ビットモードで実行することで時間コストをいくらか相殺することができますが、様々なビット幅を処理するために出現するという公開されたサンプルコードの中には、最も幅広いものをひどく誤解し、固定する。いいえ、私は手元に修理したコピーを持っていません。
追加された 著者 rossp,
私は、 getTemp が0に設定されていれば、正しい温度がシリアルに表示されていることを意味していると思います( Temperature = 0.00
追加された 著者 Towell,
あなたの編集で「修正」していることを明確にしてください。あなたのgetTemp()は時には 0 を返すので、 getTemp( 'F')== 0 をチェックすることでゼロをフィルタリングすることは明らかです。
追加された 著者 passing through,
したがって、根底にある問題を無視して、!ds.search(addr)の問題のあるインスタンスをスキップします(センサを2回連続してポーリングするだけで)。 :)
追加された 著者 passing through,
@Chris Stratton:私は、DS18B20通信の実際の問題が失敗しているかどうかを調べることをお勧めします。 BandonRandon:DallasTemperatureライブラリを試してみませんか?それはテスターのスケッチと他の有用なものも付属しています。
追加された 著者 passing through,

1 答え

断続的な通信に問題があります。

アドレス検索が失敗することがあり、 getTemp()はfalseを返します。 C ++(および他の多くの言語)では、falseは暗黙的に(int)0(float)0.0f などにキャストされます。

複数のreturn文の意味が異なるため、 getTemp()関数もデバッグするのが難しいです。

delay(250); の後で残りの部分をスキップするには return false; を実行します。

https://www.pjrc.com/teensy/td_libs_OneWire.html の例では、 return ステートメントの意味は異なります。戻り値は void loop()関数内で発生します。この関数は、(値を返さずに)現在の実行を中断し、次のループを続けることを意味します。

一般的には複数の return を持つのは大丈夫ですが、問題になることがありますので、避けることをお勧めします。

フォールトを検出する機能を維持しながらこれをクリーンアップしたい場合、いくつかのオプションがあります(ほとんどのものから最も推奨されないものまで)。

  • do the setup/checking in a different function (and only call the second one if the first one succeeded), i.e. if (isReady()) { Serial.println(getTemp()); }
  • set a separate error variable, i.e. error = true; return 0; (and then check error later)
  • define a 'default' value that you interpret as an error (and never expect to be a temperature), i.e. return NAN;//not a number
1
追加された
愚かな値のように見える -460.0f ではなく、 NAN数字ではありません)。それは「有効な価値ではない」という意味をより明確に伝えます。 Serial.print()は "nan"と表示します。
追加された 著者 Sprogz,
ありがとうございました。Miles Burton Libraryに切り替えました。すべてが期待どおりに動作していて、コードがはるかにきれいに見えます。
追加された 著者 Towell,
実際にセンサーを難しい方法で使用し、ライブラリを使用しない理由はありますか(OneWireと同じように)? OneWireを使用するDallas温度ライブラリがあります。 github.com/milesburton/Arduino-Temperature-Control-Library
追加された 著者 passing through,
ええ、範囲外は私が思いついた最初のものでした。それが私の最も推奨されない解決策であるため、NANを使用していても、それはまだ劣っているとみなします。私はそれに応じて私の答えを編集する。
追加された 著者 passing through,