Датчик DS18B20 вычисление отрицательной температуры.

При вычисление отрицательных значений температуры, не опытному, в этом плане любителю (как мне),
легко сделать не очевидную и не вычисляемую при эксплуатации ошибку.
Формат предоставления данных в датчике DS18B20 представлен в даташите табличкой:

И очень соблазнительно для точности 1градус, включить преобразование с точностью 9бит, и строчкой
temp=(StratchPad[0]>>4)|(StratchPad[1]<<4); получить знаковые 8 битные данные.
но при таком подходе, у меня вычисленные значения расходятся с табличкой из даташита.
В таблице 0xFF5E это -10,125С, а у меня получается 0xF5 это -11С
В таблице 0xFE6F это -25,0625C, а у меня получается 0xE6 это -26С
В таблице 0xFC90 это -55С, вот тут совпадение С9 это -55С
Пробуем перехитрить и просто инвертировать без добавления 1
~0xF5=0xA, ура 10С совпало!!!
~0xE6=0x19 ура 25С опять совпало!!!
~0xC9=0x36 блин 54С не совпало.
Решение оказалось простым надо сначала перевести из дополнительного кода в прямой, а потом отбрасывать лишние биты
((~0xFF5E)+1)>>4=0xA =10C(минус учитывается в программе)
((~0xFE6F)+1)>>4=0x19 =25C
((~0xFC90)+1)>>4=0x37=55C
ЗАРАБОТАЛО )))
  • -1
  • 08 августа 2016, 21:39
  • FreeLand

Комментарии (17)

RSS свернуть / развернуть
а пробовали просто присвоить значение c типом int16_t?
а потом если нужны градусы — просто делим на 16 именно делим а не сдвигаем.
Результат тот же
можно и float приаттачить, типа
float temp = (float)StratchPad / 16;
получите температуру с точнотью 1/16 градуса
0
StratchPad конечно предварительно должен иметь тип int16_t
0
а вообще из курса математики, чтобы отрицательное число преобразовать в положительное нужно его отнять из нуля. |x| = 0 — x, если x <= 0
поэтому не инвертировать нужно и прибавлять единицу, а отнимать число от нуля

(0 - 0xFF5E) >> 4 = 0xA /*по сути 0xFF5E - это -162 в int16_t, и если его поделить на 16, то получим -10.125*/
0
Mihail, статья называется не «Оптимальное преобразование числа из дополнительного кода в прямой».Она об ошибке при вычисление отрицательной температуры датчика DS18B20 с округлением, которая выглядит логично и которую я видел в других исходниках. И то что я на пальцах перевел в прямой код, это просто чтобы показать что сначала надо код преобразовать, потом округлять.
0
которая выглядит логично
для меня это выглядит нелогичным. Логичное и математически верное решение я уже привел
0
Ну значит пост адресован не Вам, может статься что я один такой темный, а другие мужики все в курсе)))
0
Mihail, когда исходник программы занимает 60К и измерение температуры совсем не главное, становишься скромнее в использовании float, и стараешься минимизировать любые конструкции, тем более ошибка для меня была совсем не очивидна. StratchPad это массив, где температура занимает 2 байта, и преобразовать ее во float так как вы написали невозможно. Максимум сначала присвоить адрес байта указателю на int16 с явным преобразованием типа. И то надо смотреть в каком порядке следуют байты в компиляторе, может понадобиться байты местами поменять.
0
float — это так, лишь на закуску. У вас в корне неправильные суждения. Преобразования странные. Неужели вы не знакомы, как организован знаковый числовой ряд char, short, int?
А ведь микросхема выдает именно в формате short…
0
Ваш компилятор обрабатывает числа как LITTLE ENDIAN или BIG ENDIAN? Для меня вопрос не однозначный, в некоторых компиляторах также short int имеет размер 1 байт, а int 2 байта.
0
float в плане экономии на размере программы есть смысл либо не использовать совсем, либо меньше заморачиваться. Потому как библиотеки для работы с ним подтягиваются даже при однократном использовании и потом, если выполняются те же математические операции, то на вызовах библиотечных функций особо уже не сэкономишь.
А вообще, в таких задачах очень уместно использование чисел с фиксированной запятой.
+1
DOOMSDAY я это знаю, пост о том что отбрасывать не значащие биты у числа представленного в дополнительном коде нельзя, у отрицательных чисел будут ошибки, это для меня было не очевидно, поэтому и написал.
0
 у отрицательных чисел будут ошибки
У положительных тоже будут. Давайте возьмем 000Fh, это 15/16 = 0,9375, а при сдвиге мы получим 0. Это особенность «округления» отбрасыванием младших разрядов, она проявит себя и для положительных и для отрицательных чисел.
0
Ну да, просто для положительных чисел 25.9375 это еще 25, а для отрицательных чисел -24.0625 это уже -25
0
Но при описанном в посте округлении, это будет -24, для меня привычнее так.
0
ИМХО, лучше тогда сделать математическое округление. Достаточно перед сдвигами к числу прибавить 0.5 (0x0008)
0
Да, так будет еще ближе к истине.
0
А то с погрешностью DS18B20 ошибка уже в 2 градуса набегает без правильного округления.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.