Датчик температуры DS18B20 возвращается как функция поплавка, возвращающая значение в 50% случаев

Я просто получил датчик температуры DS18B20 и пытаюсь изменить код примера, чтобы использовать функцию. Ниже приведена моя функция getTemp . Он работает, но возвращает результаты с помощью 0-значной части времени, например:

Температура = 72,39 o   Температура = 0,00

Если я добавлю Serial.print (fahrenheit); внутри функции, я всегда получаю правильную температуру. Хотя это может быть связано с необходимостью задержки, но с добавлением задержки (5000); в моем цикле не помогло.

Я предполагаю, что это что-то просто, я не понимаю, как возвращается floats .

#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
По-видимому, на рынке существует много предполагаемых устройств «DS18B20», которые не соответствуют срокам опубликованной спецификации. Чтобы попытаться использовать их, вам нужно будет замедлить работу. Вы можете несколько компенсировать временные затраты на это, работая в режиме с более низкими битами, но некоторые из опубликованного примера кода, который появляется для обработки различных бит ширины, на самом деле ужасно неправильно истолковывает что-либо, кроме самого широкого, и имеет Быть исправленным. Нет, у меня нет исправленной копии, чтобы процитировать.
добавлено автор rossp, источник
Я предполагаю, что я имею в виду, что если getTemp установлен в 0, то правильная температура отображается на последовательный (никогда не отображается Temperature = 0.00 ) Он возвращает только фактическую температуру.
добавлено автор Towell, источник
Не могли бы вы прояснить, что вы подразумеваете под «исправлениями» в вашем редактировании? Поскольку ваш getTemp() иногда возвращает 0 , ясно, что вы фильтруете нуль, проверяя getTemp ('F') == 0 .
добавлено автор passing through, источник
Таким образом, вы пропускаете проблемные экземпляры ! Ds.search (addr) (путем простого опроса датчика дважды подряд), игнорируя основную проблему. :)
добавлено автор passing through, источник
@Chris Stratton: Я думаю, что неплохо заглянуть в реальную проблему с сбоем связи DS18B20. BandonRandon: Почему бы вам не попробовать библиотеку DallasTemperature? Он даже поставляется с эскизом тестера и другими полезными материалами.
добавлено автор passing through, источник

1 ответы

У вас проблемы с прерывистыми коммуникациями.

Иногда ваш поиск по адресам терпит неудачу, а getTemp() возвращает false. В C ++ (и многих других языках) false будет неявным образом передаваться в (int) 0 , (float) 0.0f и т. Д.

Функция 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, например. github.com/milesburton/Arduino-Temperature-Control-Library .
добавлено автор passing through, источник
Да, выход из диапазона был первым, что я придумал. И поскольку это мое наименее рекомендуемое решение, я по-прежнему считаю его неполным даже при использовании NAN. Я соответствующим образом отредактировал свой ответ.
добавлено автор passing through, источник
Анархическая электроника
Анархическая электроника
1 510 участник(ов)

[около] электронные темы. без переходов на личности, стен стикеров, политики, непрошенной рекламы и всякого такого Основной чат у нас в @ru_electronics Общий информационный канал @ru_electronics_feed

Про электронику
Про электронику
1 461 участник(ов)

QA чат для решения вопросов, связанных с электроникой. без стикеров, непрошенной рекламы и игр в русский форум оформляйте вопрос в одно сообщение вопросы со словом «кто» игнорируются don't ask for ask Правила http://telegra.ph/ru-electronics-rulz-11-11

Embedded Group
Embedded Group
873 участник(ов)

Все про Embedded и электронику. Осторожно, бывают нотификейшены. #вопросподелу - Для поиска вопросов и ответов #devtools - фотки рабочих железок Работа: @rabotaembedded http://embedded.group http://vk.com/embedded_space

Hardware & Radio
Hardware & Radio
155 участник(ов)

Разговоры об электронике, микроконтроллерах, низкоуровневом программировании, реверс-инжиниринге, FPGA, квадрокоптерах, 3D-печати, Software Defined Radio, любительском радио, и всяком таком.

ARDUINO [RU]
ARDUINO [RU]
60 участник(ов)

Обсуждение Электронного конструктора Arduino. Проблемы и их решения. Ссылки на интересные статьи и проекты. ВК: https://vk.com/arduino_esp Realtek: http://vk.com/rtl8711 Чаты: IOT https://t.me/ProIOT esp8266 https://t.me/Proesp8266