DS18B20 Temperatuursensor retourneert als vlotterfunctie 50% van de tijd nul terug

Ik heb net een DS18B20-temperatuursensor gekregen en probeer de voorbeeldcode aan te passen om in plaats daarvan een functie te gebruiken. Hieronder is mijn getTemp -functie. Het werkt maar de resultaten worden geretourneerd met een 0-waarde, een deel van de tijd bijvoorbeeld:

Temperatuur = 72,39
  Temperatuur = 0.00

Als ik Serial.print (fahrenheit); in de functie toevoeg, krijg ik altijd de juiste temperatuur. Ik dacht dat dit misschien te maken had met een vertraging, maar het toevoegen van delay (5000); in mijn lus hielp niet.

Ik ga ervan uit dat het iets eenvoudigs is. Ik begrijp niet hoe drijft terugkeert.

#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' ) );


}

Bewerk: Interessant genoeg, het toevoegen van een if -instructie aan de lus herstelt dit echter. Ik wil nog steeds graag begrijpen wat er aan de hand is:

void loop(void) {
  if ( getTemp( 'F' ) == 0 ){
    Serial.print( "Temperature = " );
    Serial.println( getTemp( 'F' ) );
  }
}
0
Er zijn blijkbaar veel zogenaamde "DS18B20" -apparaten op de markt die niet voldoen aan de timing van de gepubliceerde specificaties. Om te proberen ze te gebruiken, moet je dingen vertragen. Je kunt de tijdskosten hiervan enigszins compenseren door een lagere bitsmodus uit te voeren, maar een deel van de gepubliceerde voorbeeldcode die verschijnt om verschillende bitbreedtes te verwerken, interpreteert eigenlijk vreselijk verkeerd, behalve de breedste, en heeft gemaakt worden. Nee, ik heb geen gerepareerde kopie bij de hand om te citeren.
toegevoegd de auteur rossp, de bron
Ik vermoed dat ik bedoel dat als getTemp is ingesteld op 0, de juiste temperatuur serieel wordt weergegeven (nooit temperatuur = 0.00 wordt weergegeven, wordt alleen de werkelijke temperatuur geretourneerd.
toegevoegd de auteur Towell, de bron
Kun je alsjeblieft verduidelijken wat je bedoelt met 'reparaties' in je bewerking? Aangezien uw getTemp() af en toe 0 retourneert, is het duidelijk dat u voor nul filtert door te zoeken naar getTemp ('F') == 0 .
toegevoegd de auteur passing through, de bron
Dus sla de problematische exemplaren van ! Ds.search (addr) over (door de sensor twee keer kort achter elkaar te vragen) en negeer het onderliggende probleem. :)
toegevoegd de auteur passing through, de bron
@Chris Stratton: Ik denk dat het een goed idee is om te kijken naar de feitelijke kwestie van de mislukking van de DS18B20-communicatie. BandonRandon: Waarom probeert u de DallasTemperature-bibliotheek niet? Het komt zelfs met een Tester-schets en andere nuttige dingen.
toegevoegd de auteur passing through, de bron

1 antwoord

U hebt intermitterende communicatieproblemen.

Uw adresonderzoek lekt af en toe en getTemp() levert false op. In C ++ (en vele andere talen) wordt false impliciet gebruikt voor (int) 0 , (float) 0.0f , enzovoort.

Uw functie getTemp() is ook moeilijk te debuggen, omdat de herhaalde verklaringen een andere betekenis hebben.

Na de delay (250); doe je een return false; om de rest over te slaan.

In het voorbeeld op https://www.pjrc.com/teensy/td_libs_OneWire.html de betekenis van de return -instructie (s) is anders. Daar gebeurt de terugkeer binnen de functie void loop() , waarbij het eenvoudig betekent om de huidige uitvoering te onderbreken (zonder een waarde te retourneren) en door te gaan met de volgende lus.

Hoewel het over het algemeen goed is om meerdere retour te hebben, kan het soms problematisch zijn en ik raad aan het te vermijden.

Als je dit wilt opruimen en toch de mogelijkheid wilt behouden om een ​​fout te detecteren, heb je een aantal opties (volgorde van meest tot minst aanbevolen):

  • 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
toegevoegd
In plaats van -460.0f , dat eruitziet als een gekke waarde, zou ik NAN (dat wil zeggen geen nummer ). Het geeft duidelijker de betekenis weer van "geen geldige waarde". Serial.print() geeft het weer als "nan".
toegevoegd de auteur Sprogz, de bron
Bedankt is overgeschakeld naar de Miles Burton Library en alles werkt zoals verwacht en mijn code ziet er veel schoner uit.
toegevoegd de auteur Towell, de bron
Is er eigenlijk een reden waarom u de sensor op de harde manier gebruikt en er geen bibliotheek voor gebruikt (zoals u met OneWire doet)? Er zijn Dallas-temperatuurbibliotheken die OneWire gebruiken, b.v. github.com/milesburton/Arduino-Temperature-Control-Library .
toegevoegd de auteur passing through, de bron
Ja, buiten bereik was het eerste dat ik bedacht. En omdat het mijn minst aanbevolen oplossing is, beschouw ik het nog steeds als inferieur, zelfs als ik NAN gebruik. Ik bewerk mijn antwoord dienovereenkomstig.
toegevoegd de auteur passing through, de bron