реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> DS18B20 + Mega помогите !, траблы с отрицательной температурой
КСПшник
сообщение Nov 13 2006, 08:40
Сообщение #16


Участник
*

Группа: Свой
Сообщений: 57
Регистрация: 7-09-05
Пользователь №: 8 307



На самом деле здесь все просто. Температура читается из ОЗУ 18B20. Причем сама температура содержится в первых двух байтах (мл. байт по мл. адресу). Так вот, считывать эту температуру необходимо в двухбайтовую переменную (например, unsigned short). Далее, анализируете старший бит этой переменной, он всегда (вне зависимости от разрядности преобразования) говорит о знаке температуры (0 - положительная, 1 - отрицательная). Так вот, если отрицательная, то сама значащая часть (см. даташит), зависящая от заданной разрядности преобразования (по умолчанию - 12 разр.), дается в инверсном коде. Т.е. вам необходимо, при 1 в старшем разряде побитово инвертировать значение температуры, предварительно запомнив "-". Удачи.
Go to the top of the page
 
+Quote Post
freux
сообщение Nov 13 2006, 10:57
Сообщение #17


Участник
*

Группа: Новичок
Сообщений: 41
Регистрация: 7-02-05
Пользователь №: 2 473



Может приведенное ниже не столь красиво, ибо отсутствуют в выражении "всякие" там 1000, -9999 .. и другие десятичные цЫфры, зато давольно-таки оптимально, если глянуть в ассемблерный листинг:
Код
                if (buf[1] > 0x0F)
                    temperature = 0xFF00;
                else
                    temperature = 0;
                temperature = temperature | (buf[0] >> 3) | (buf[1] << 5);
                WriteOutTemp(temperature);

...
...
#pragma optimize=2
void WriteOutTemp(int temperature)
{
unsigned char nHalf = 0;
  temperature = temperature >> 1;
  if (SREG_C == 1)
      nHalf = 5;
  printf("T=%d.%d\r\n", temperature, nHalf);
}

С точностью один знак после запятой работает изумительно. А где printf, там и на индикатор вывести просто
Go to the top of the page
 
+Quote Post
Andy Great
сообщение Nov 13 2006, 11:29
Сообщение #18


Знающий
****

Группа: Свой
Сообщений: 793
Регистрация: 5-11-04
Из: Краматорск, Украина
Пользователь №: 1 057



Вопрос по той же конфигурации. Пытаюсь использовать паразитное питание, при частоте опроса до 5сек выдает завышенные показания (85 град вместо 26 комнатных). ЦРЦ в норме. Свыше 5сек в основном выдает часто нормально. Резистор по питанию 3к, паразитное питание на ноге включаю. Как только подключаю питание на 3ю ногу - все ОК. Разрядность пока не менял. ПОЧЕМУ?

Да, использую DS1822, DS18B20 пока не пробовал.

P.S.: Отвечаю сам себе. Разрядность ничего не меняет, надо ногу питания привязать к земле, как в даташите. Похоже, иначе неуверенное определение паразитного питания. При паразитном питании и 9бит преобразовании 100мс недостаточно для завершения оного, 200мс достаточно.
Go to the top of the page
 
+Quote Post
simsim
сообщение Mar 4 2007, 18:09
Сообщение #19


Участник
*

Группа: Новичок
Сообщений: 45
Регистрация: 30-10-06
Пользователь №: 21 801



signed char tt;
//ds18b20_select(0);
//w1_search(0xf0,0);
ds18b20_init(0,-35,35,DS18B20_9BIT_RES);
tt=ds18b20_temperature(0);
=========================
использую библиотеки CodeVision/
tt=-15 всегда...
что не так ?
Go to the top of the page
 
+Quote Post
=GM=
сообщение Mar 4 2007, 19:40
Сообщение #20


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(simsim @ Mar 4 2007, 15:09) *
signed char tt;
//ds18b20_select(0);
//w1_search(0xf0,0);
ds18b20_init(0,-35,35,DS18B20_9BIT_RES);
tt=ds18b20_temperature(0);
=========================
использую библиотеки CodeVision/
tt=-15 всегда...
что не так ?

9 бит не влезают в char


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
VXDRV
сообщение Mar 5 2007, 12:40
Сообщение #21


Участник
*

Группа: Свой
Сообщений: 67
Регистрация: 5-02-07
Пользователь №: 25 074



Решил наконец код привести - пример из Delphi (был под рукой), кому надо тот переведёт и на C и на ассемблер:

var
TH_TEMPERATURE:Byte;
TL_TEMPERATURE:Byte;
INT_TEMPERATURE:WORD;
SIGN:WORD;
TEMPERATURE:REAL;

собственно сама процедура:

TL_TEMPERATURE:=FT_In_Buffer[8];
TH_TEMPERATURE:=FT_In_Buffer[9];

INT_TEMPERATURE:=TH_TEMPERATURE*256+TL_TEMPERATURE;
SIGN:=INT_TEMPERATURE and $8000;
if SIGN=0 then
begin
TEMPERATURE:=INT_TEMPERATURE*0.0625;
end
else
begin
TEMPERATURE:=-(not(INT_TEMPERATURE)+1)*0.0625;
end;
Label1.Caption:=FloatToStrF(TEMPERATURE,ffFixed,6,4)

Принцип:
Определяем старший бит в двух байтах накладывая маску (SIGN:=INT_TEMPERATURE and $8000). Если SIGN равен нулю значит температура положительна - ничего не делаем умножаем и готово.
Иначе SIGN=$8000 (или 0x8000) температура отрицательна - берём инверсию, прибавляем единицу (что-то здесь связано с дополнительным кодом что ли), умножаем, добавляем минус и готово.
У меня работает - удачи!

P.S - В Windows есть очень хорошая программа - Калькулятор (calc.exe) - В инженерном виде позволяет проверить многие вещи.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Mar 5 2007, 13:20
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(VXDRV @ Mar 5 2007, 11:40) *
Решил наконец код привести

Прочитайте наконец пост номер 3.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
VXDRV
сообщение Mar 5 2007, 17:55
Сообщение #23


Участник
*

Группа: Свой
Сообщений: 67
Регистрация: 5-02-07
Пользователь №: 25 074



Цитата(zltigo @ Mar 5 2007, 13:20) *
Цитата(VXDRV @ Mar 5 2007, 11:40) *

Решил наконец код привести

Прочитайте наконец пост номер 3.


У меня просто входная величина не приведена к signed int.
Тем не менее вариант имеет право на существование.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Mar 5 2007, 19:41
Сообщение #24


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(VXDRV @ Mar 5 2007, 09:40) *
Решил наконец код привести - пример из Delphi (был под рукой), кому надо тот переведёт и на C и на ассемблер:

var
TH_TEMPERATURE:Byte;
TL_TEMPERATURE:Byte;
INT_TEMPERATURE:WORD;
SIGN:WORD;
TEMPERATURE:REAL;

собственно сама процедура:

TL_TEMPERATURE:=FT_In_Buffer[8];
TH_TEMPERATURE:=FT_In_Buffer[9];

INT_TEMPERATURE:=TH_TEMPERATURE*256+TL_TEMPERATURE;
SIGN:=INT_TEMPERATURE and $8000;
if SIGN=0 then
begin
TEMPERATURE:=INT_TEMPERATURE*0.0625;
end
else
begin
TEMPERATURE:=-(not(INT_TEMPERATURE)+1)*0.0625;
end;
Label1.Caption:=FloatToStrF(TEMPERATURE,ffFixed,6,4)

Принцип:
Определяем старший бит в двух байтах накладывая маску (SIGN:=INT_TEMPERATURE and $8000). Если SIGN равен нулю значит температура положительна - ничего не делаем умножаем и готово.
Иначе SIGN=$8000 (или 0x8000) температура отрицательна - берём инверсию, прибавляем единицу (что-то здесь связано с дополнительным кодом что ли), умножаем, добавляем минус и готово.
У меня работает - удачи!

P.S - В Windows есть очень хорошая программа - Калькулятор (calc.exe) - В инженерном виде позволяет проверить многие вещи.

Не пойму, зачем такие сложности? Почему нельзя вот так?
Код
         TL_TEMPERATURE:=FT_In_Buffer[8];
         TH_TEMPERATURE:=FT_In_Buffer[9];
         INT_TEMPERATURE:=TH_TEMPERATURE*256+TL_TEMPERATURE;
         TEMPERATURE:=INT_TEMPERATURE*0.0625;

Ну будет переменная TEMPERATURE отрицательной, ну и что? Принтф или FloatToStrF точно так же её напечатает, как и положительную, только со знаком минус.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
Naksojin
сообщение Mar 6 2007, 18:52
Сообщение #25





Группа: Новичок
Сообщений: 1
Регистрация: 10-10-06
Пользователь №: 21 181



Я когда-то вот так делал....

unsigned char Check_Minus (unsigned char in_data)
{
if ((in_data & 0x80) != 0)
{
display.minus = ON;
return (~in_data + 1);
}
else
{
display.minus = OFF;
return in_data;
}
}

Вариантов много.

Сообщение отредактировал Naksojin - Mar 6 2007, 18:53
Go to the top of the page
 
+Quote Post
umup
сообщение Mar 6 2007, 19:27
Сообщение #26


Местный
***

Группа: Свой
Сообщений: 226
Регистрация: 2-06-06
Пользователь №: 17 720



Для преобразования в формат с фиксированной запятой (1 знак после запятой) я исп. такую ф-ю :
Код
int16_t ds1w_12bit_to_celsius(uint16_t value)
{uint8_t uc1;
uc1 = (value>>8) & 0x80; //запомнить знак числа
if (uc1) value = 0-value; //если нужно, проинвертировать
value = (value>>1) + (value>>3); //скорректировать
if (uc1) value = 0-value; //восстановить знак
return(value);
}


Сообщение отредактировал umup - Mar 6 2007, 19:32
Go to the top of the page
 
+Quote Post
Рома_С
сообщение Mar 10 2007, 23:25
Сообщение #27





Группа: Новичок
Сообщений: 8
Регистрация: 23-01-07
Пользователь №: 24 699



Помогите мне пожалуйста, тоже проблемы с отрицательной температурой правда только пробовал я это в Proteuse 6,9 SP3, пока нет возможности попробовать на реальных термодатчиках в протеусе он мне как бы измеряет отрицательную температуру но показывает вместо -1 число 4095, вместо -2 число 4094, вместо -3 число 4093 и так далие. В чем же дело, все это я сделал из примера в CodeVision для ds18b20, или это Протеус глючит, или это я так глючу smile.gif . Как мне сделать, чтобы минусовая температура отображалась как надо в десятичном виде, и как можно отобразить на дисплее hd44780 температуру в двоичном виде ибо значение температуры в ds18b20 занимает два байта. Как это все сделать в CodeVision.

Заранее спасибо.

Сообщение отредактировал Рома_С - Mar 10 2007, 23:27
Go to the top of the page
 
+Quote Post
=GM=
сообщение Mar 11 2007, 01:22
Сообщение #28


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(Рома_С @ Mar 10 2007, 20:25) *
Помогите мне пожалуйста, тоже проблемы с отрицательной температурой правда только пробовал я это в Proteuse 6,9 SP3, пока нет возможности попробовать на реальных термодатчиках в протеусе он мне как бы измеряет отрицательную температуру но показывает вместо -1 число 4095, вместо -2 число 4094, вместо -3 число 4093 и так далие. В чем же дело, все это я сделал из примера в CodeVision для ds18b20, или это Протеус глючит, или это я так глючу smile.gif . Как мне сделать, чтобы минусовая температура отображалась как надо в десятичном виде, и как можно отобразить на дисплее hd44780 температуру в двоичном виде ибо значение температуры в ds18b20 занимает два байта. Как это все сделать в CodeVision.

Так и должно быть, никто никого не глючит. Минус единица (-1) представлена в дополнительном коде. Чтобы получить положительное число, надо проинвертировать каждый бит и к результату добавить 1.
Для -1 будет так: 4095=0xFFF, инв(0хFFF)+1=1. Для -2 будет так: 4094=0xFFE, инв(0хFFE)+1=2. И т.д.

Отсюда следует простой алгоритм: проверяете 11 бит числа, если он равен 1, значит число отрицательное. Получаете дополнение, это одна команда NEG Rx.

Преобразование в символьную форму можно осуществить разными путями. Один из них следующий. Поскольку весь диапазон 16-битных чисел со знаком лежит от -32768 до +32767, то надо определить 5 цифр. Старшая цифра, десятков тысяч может быть 0, 1, 2 или 3. Вычитаете из числа значение 10000 столько раз, чтобы число стало меньше 10000. Количество вычитаний вам даст цифру десятков тысяч. Затем из остатка вычитаете 1000 подобным образом, затем 100 и 10. Последний остаток даст вам количество единиц в числе.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
Рома_С
сообщение Mar 11 2007, 18:17
Сообщение #29





Группа: Новичок
Сообщений: 8
Регистрация: 23-01-07
Пользователь №: 24 699



А если нужно чтобы температура отображалась сточностю -0,1 или даже -0,05 то как из float сделать стринг?
Go to the top of the page
 
+Quote Post
VXDRV
сообщение Mar 12 2007, 00:39
Сообщение #30


Участник
*

Группа: Свой
Сообщений: 67
Регистрация: 5-02-07
Пользователь №: 25 074



Дискретность 0,0625 если вы посмотрите DATA_SHEET. Предлагаю вариант вообще без float - (господин GM - может к этому шёл) полученные два байта приводите к INT с корекцией знака (знак запоминаете во флаге каком нибудь) и умножаете на 625 результат - long int
Например 0x01 - типа старший байт 0x40 младший - в общем 0x140 * 625=200000. Ставим запятую после двадцать на самом индикаторе затем рисуем "дробную" часть получаем 20,0000 С. Алгоритм вычисления десятков сотен и т.д. приведён постом выше.
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 10th July 2025 - 07:26
Рейтинг@Mail.ru


Страница сгенерированна за 0.01486 секунд с 7
ELECTRONIX ©2004-2016