DS18b20 мороз с разрешением 0,1 градуса

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Mursik
Мудрый кот
Сообщения: 1763
Зарегистрирован: Вт мар 28, 2023 21:17:15
Откуда: Universe

DS18b20 мороз с разрешением 0,1 градуса

Сообщение Mursik »

Возник вопрос по сабжу (решил быстренько слепить термометр на 7-сегментном индикаторе). Если с целыми положительными температурами вопросов не возникло (сдвинул результат преобразования на 4 бита вправо) и получил градусы.
То с отрицательными появились непонятки.
Обычно на форумах вижу преобразование из отрицательных значений через побитовую инверсию с добавлением единицы к результату. Вроде как работает в протеусе, хотя при некоторых значениях получается на 1 больше почему то.
Но главная непоянтка с долями градуса.

ИИ в гугле советует сделать всё просто:

int16_t raw_temp = (raw_data_byte2 << 8 ) | raw_data_byte1; // Combine bytes
float temp_C = (float)raw_temp / 16.0; // For 12-bit (0.0625)

Получаем результат с плавающей точкой. Но мне не хотелось бы к плавучке приходить из за сложностей потом на разряды индикатора её выдёргивать.

А инверсия побитовая с добавлением единицы у меня почему то даёт не тот результат..

Как правильно тот скратчпад 16 бит преобразовать из отрицательных температур?

:?
I have a dream...¯\_(ツ)_/¯
Аватара пользователя
JackSmith
Потрогал лапой паяльник
Сообщения: 332
Зарегистрирован: Ср мар 09, 2016 08:07:41

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение JackSmith »

Код: Выделить всё

                  uint16_t temp=ds18b20_read();
                  uint16_t frac= ((temp & (uint16_t)0x0f)*10)/16;
                  temp >>= 4;
frac - дробная часть, tmp - целая часть, для отрицательных температур очищайте знаковые старшие биты.
Аватара пользователя
АлександрЛ
Друг Кота
Сообщения: 43767
Зарегистрирован: Пн ноя 30, 2009 03:00:01
Откуда: Нерезиновая

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение АлександрЛ »

:dont_know:
Лет 15 назад я делал термометр на Tiny2313 и DS18B20-
СпойлерИзображение
Схема термометра.PNG
(34.82 КБ) 533 скачивания
Нормально он минус показывает.. :dont_know:
Изображение
СпойлерМодель в протеусе сделана на AT90S2313, "в железе" работает на Tiny2313.
Прошивка позволяет работать с одним и двумя термодатчиками.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15539
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение BOB51 »

Под ассемблером там проблем нет.
Вроде и под Си ардуиняче чего то было...
:?
Аватара пользователя
AlexS4
Друг Кота
Сообщения: 6646
Зарегистрирован: Пт сен 10, 2021 15:19:36
Откуда: Протвино

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение AlexS4 »

а там вроде старший байт заполнен раскопированным битом знака обзовем unsigned char h_raw
а младший байт (unsigned char l_raw) это само значение signed c младшим битом ценой в 0.5C
по сути это означает что если загрузить это в signed int16 и разделить на 2
то знак будет знаком, а модуль будет модулем. а младший выдвинутый бит если задвинуть с младшей стороны в char и умножить на 5 - дробной частью.

а если хотим модуль на коленке без abs() и прочей высшей математики :)) , а с простейшей аля asm,
то примерно так думаю сойдет:

Код: Выделить всё

unsigned char  h_raw, l_raw, sign, tempmodule,tempdecimals;
sign=h_raw & 01 ;                       // 0 -> +C  1 -> -C
tempdecimals=(l_raw & 01)* 5 ;  //  xxx.0C or xxx.5C
if(sign) l_raw= 0xFF - l_raw ;      //below  zero C. so, negative to absolute value conversion  
tempmodule=l_raw >> 1 ;           //integer part С
ну понятно что там всего 2 или 3 переменные (регистра) нужны,
остальные для наглядности исключительно..


не проверял, если накосячил скандачка спросони :dont_know: ... вобщем настоящий кот поленится пинать :)
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение akl »

Как вариант. Проверяется принятый результат, знак запоминается. Если отрицательный, конвертируется. Умножается на 10 и сдвигом делится на 16. К полученному результату прибавляется значение флага C для правильного округления.
Спойлер

Код: Выделить всё

; Считанные данные находятся в R11:R12
; ZH=0
LCD_CONVERT:
	CBI	ACSR,MINUS	; очистить признак минусового результата
	
	CLR	R10
	
	TST	R11
	BRPL	GO_PLUS
	COM	R11
	COM	R12
		
	ADC	R12,ZH
	ADC	R11,ZH
	SBI	ACSR,MINUS	; установить признак минусового результата
GO_PLUS:
	RCALL	MULT10
;R10,R11,R12 результат старший-младший
	LSR	R10
	ROR	R11
	ROR	R12

	LSR	R10
	ROR	R11
	ROR	R12

	LSR	R10
	ROR	R11
	ROR	R12

	LSR	R10
	ROR	R11
	ROR	R12
; разделить полученное значение на 16, чтобы
; получить десятичный эквивалент результата 
	ADC	R12,ZH
	ADC	R11,ZH
	ADC	R10,ZH		; округление результата

	RCALL	KALK1
	RET	
;************************************************
Аватара пользователя
Mursik
Мудрый кот
Сообщения: 1763
Зарегистрирован: Вт мар 28, 2023 21:17:15
Откуда: Universe

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение Mursik »

Короче, психонул и решил начать с ..протеуса. Думаю, а вдруг это он мне мозг выносит?
Решил выплёвывать в терминал получаемые два байта скратчпада температуры.

Изображение

24,6 - 0x0188
24,5 - 0x0188
24,4 - 0x0180
24,3 - 0x0180
24,2 - 0x0180
24,1 - 0x0180
24,0 - 0x0180

Код: Выделить всё

		write_byte(0xCC);				//skip ROM
		write_byte(0xBE);				//read scratch
		Tmp1 = read_byte();
		Tmp2 = read_byte();
		putc(0xAA);
		putc(0xAA);
		putc(Tmp2);
		putc(Tmp1);
		putc(0xCC);
Короче, выходит моделька DS18b20 дробную часть как то странно выдаёт. :shock:
I have a dream...¯\_(ツ)_/¯
Аватара пользователя
linux_rulezz
Вымогатель припоя
Сообщения: 585
Зарегистрирован: Пн сен 15, 2025 08:43:23
Откуда: Маленький СССР посреди шариатской республики

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение linux_rulezz »

У него ж точность ±1.5℃ в расширенном диапазоне температур, а воспроизводимость ±0.5℃. Зачем вообще пытаться из этого УГ пытаться получить температуру?
Возьмите уж NTC…

Добавлено after 1 minute 27 seconds:
Mursik, а это точно B, а не S?
Windows must die!
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение roman.com »

а в чём собственно вопрос ?
для начала как обычно смотрим даташит...

Изображение

видим что при отрицательных температурах получаем отрицательное число (единица в первом разряде).

а далее всё как обычно... работа со знаковыми переменными...

//DEC -0...-2.147.483.648 | 0...2.147.483.647
//HEX -80 00 00 00...ff ff ff ff | 0...7f.ff.ff.ff
Вложения
Screenshot_1.jpg
(56.76 КБ) 470 скачиваний
Novice user
Мудрый кот
Сообщения: 1704
Зарегистрирован: Вт янв 05, 2016 10:14:25
Откуда: поселок Мелеуз

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение Novice user »

[uquote="Mursik",url="/forum/viewtopic.php?p=4774723#p4774723"]выходит моделька DS18b20 дробную часть как то странно выдаёт. :shock:[/uquote]
Проверил у себя,шаг в свойствах DS18B20 поставил 0,0625,работает норм,вот снижал от 24,5 до 23,9 с шагом 0,0625

Изображение
А здесь снижаю с -0,0625 до -0,625
Изображение
Аватара пользователя
Mursik
Мудрый кот
Сообщения: 1763
Зарегистрирован: Вт мар 28, 2023 21:17:15
Откуда: Universe

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение Mursik »

Продолбался с протеусом (v9), плюнул, стал из даташита ту таблицу тупо в программе подсовывать вместо полученного с датчика значения - получил заданные значения.
Стало быть моделька в протеусе врёт. :cry:
На опцию "granularity" в настойках модель не реагирует - выдаёт сильно грубый шаг.
I have a dream...¯\_(ツ)_/¯
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15539
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение BOB51 »

Первое действие
temp=(~temp)+1
разделяем старшую часть и младшие 4 бита (включено 12 разрядное преобразование)
temp_h = temp >> 4
temp_l = temp & 0x000f
далее декодирование целой части в код сегментов целых
Записать коды сегментов "минус" и "запятая" в соответствующие знакоместа дисплея
Получить значение дробной части в целых числах исходя из веса разрядов в ранее выделенной младшей тетраде данных
бит 3 = 5000
бит 2 = 2500
бит 1 = 1250
бит 0 = 625
далее обработать получившийся результат для вывода в раздел индикатора, выделенный для дробной части.
Воть как то так ...
8)
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение Аlex »

Блин, вы серьёзно ?
Если на Сях, то всё очень просто. Тупо берём и считываем с датчика 2 байта в знаковую переменную. И всё, получаем температуру с необходимым разрешением и знаком.
Для перевода в градусы, просто делим значение на 16 (для "B", разрешение 0.0625) или на 2 (для "S", разрешение 0.5).
Всё.
Аватара пользователя
Mursik
Мудрый кот
Сообщения: 1763
Зарегистрирован: Вт мар 28, 2023 21:17:15
Откуда: Universe

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение Mursik »

[uquote="Аlex",url="/forum/viewtopic.php?p=4774764#p4774764"]Для перевода в градусы, просто делим значение на 16 (для "B", разрешение 0.0625) или на 2 (для "S", разрешение 0.5).
Всё.[/uquote]

Беда такого деления в плавучем результате. Если куда printf() плевать оно конечно само разгребет, но если ручками на 7-сегментный индикатор раскладывать, тут тут геморно с флоат воевать :?
I have a dream...¯\_(ツ)_/¯
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15539
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение BOB51 »

Алгоритм со времён ассемблера однако.
Где там быстро математику сделать?
Заодно и в сегментный код перекинуть проще.
8)
Novice user
Мудрый кот
Сообщения: 1704
Зарегистрирован: Вт янв 05, 2016 10:14:25
Откуда: поселок Мелеуз

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение Novice user »

Вот в баском,переменные только Т=два байта,остальные один байт,проверил в протеусе.

Код: Выделить всё

Byte0 = 1wread()           ' Читаем нулевой байт
Byte1 = 1wread()           ' Читаем первый байт
Print  HEX(Byte1);HEX(Byte0)
If Byte1 > 248 Then        ' Проверка на отрицательность температуры
Byte0 = &HFF - Byte0
Byte1 = &HFF - Byte1
Byte0 = 1+ Byte0
Sign = "-"
End If
T = Byte1*16            ' Сдвигаем  первый байт вправо на 4 бита (2*2*2*2=16)
T1 = Byte0/16           ' Сдвигаем нулевой байт влево на 4 бита (2*2*2*2=16)
t1=t1+t                    'Целая часть
t=Byte0 And 15          'дробная часть
t=10*t                  'умножаем на 10 и делим на 16
t=t/16
print t1;".";t
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение Аlex »

Mursik писал(а):Беда такого деления в плавучем результате.
Что такое "Плавучий результат" ? Поясните.
Mursik писал(а):тут геморно с флоат воевать
Зачем тут флоат нужен ? Все операции можно делать с целыми числами.

PS: В чём вообще проблема, не могу понять ? Вам же градусник уже отдаёт готовую температуру, умноженную на разрешение (2 или 16).
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение akl »

[uquote="Аlex",url="/forum/viewtopic.php?p=4774764#p4774764"]Тупо берём и считываем с датчика 2 байта в знаковую переменную. И всё, получаем температуру с необходимым разрешением и знаком.
Для перевода в градусы, просто делим значение на 16 (для "B", разрешение 0.0625)...
Всё.[/uquote]Потеряли дробную часть.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение Аlex »

akl писал(а):Потеряли дробную часть.
Ну, так, умножаем на 10, 100 (или сколько нужно), а потом делим. И получаем фиксированную точку.
Всё же элементарно...
Аватара пользователя
Thinnnfor
Вымогатель припоя
Сообщения: 590
Зарегистрирован: Пн июн 03, 2024 22:29:24

Re: DS18b20 мороз с разрешением 0,1 градуса

Сообщение Thinnnfor »

Код: Выделить всё

           aaa (unsigned char dev)  // функция считывания t с датчика номер(dev) и вывод значения
                                 //  на лсд с отбросом незначащих нулей (до запятой)
                {          
                      tem=ds18b20_temperature(&ee_code[dev][0])*10; //считываем и умножаем на 10
                           
                       if (tem<0)      // если показание отрицательное
                      {
                            lcd_putsf("-");  //выводим "-" на лсд
                            tem=-tem;        //инвертируем показание 
                     
                      }
                 
                     if (tem<1260) {
                     

                                     if (tem>=1000) goto la1;
                                      if (tem>=100) goto la2;  // отброс незначащих нулей
                                       goto la3 ;             // тоже отброс незначащих нулей
                             la1:           lcd_putchar(tem/1000+48);      // сотни 
                             la2:           lcd_putchar(tem%1000/100+48);  // десятки
                             la3:           lcd_putchar((tem%100)/10+48);  // единицы
                                            lcd_putchar(44);              // запятая
                                            lcd_putchar(tem%10+48);      // десятые градуса
                                            lcd_putchar(223);            // градус °
                                            lcd_putsf("C ");            //C цельсия    
                                     }
                    else lcd_putsf("Err     ");// если t<1260 выводим на лсд
                                                                    // иначе выводим "Err" (ошибка)
                      
                 }
Добавлено after 1 minute 6 seconds:
signed int tem;
Ответить

Вернуться в «Разные вопросы по МК»