Свежие обсуждения
Микроконтроллеры

Библиотека для DS1621 - разрешение 0.1 °С

Не знал, куда кинуть - то ли в Удачный опыт, то ли сюда - но тут ближе к теме. Столкнулся с необходимостью измерения температуры с высоким разрешением, решил использовать упомянутый в теме датчик. Нижеприведенная библиотека позволяет читать данные с дополнительных регистров датчика (в соответсвии с datasheet на него) и вычислять температуру с высоким разрешением. Функция возвращает значение температуры(целое число), умноженное на 10 (сотые доли не округляются, а отбрасываются). Т.е. при температуре 37.5 °С функция вернет 375. Написано для CodeVision. Буду рад, если кому-то пригодится.

Заголовочный файл:

/* 1621.h */

/*
CodeVisionAVR C Compiler
(C) 2001 Pavel Haiduc, HP InfoTech S.R.L.

*/

#ifndef _1621_INCLUDED_
#define _1621_INCLUDED_

#include <i2c.h>

#pragma used+

void ds1621_init(void);
void ds1621_start(void);
int ds1621_read(void);

#pragma used-
#pragma library 1621.lib

#endif

/* end of file */

Библиотечный файл:


/******************************************************************

1621.lib

/* ЛИРИЧЕСКОЕ ОТСТУПЛЕНИЕ */
/* По даташиту на DS1621 максимальное время преобразования - 750мс,
однако, при интенсивной работе с датчиком замечено, что при частых
обращениях, или при работе в режиме непрерывных преобразований, он
несколько завышает показания - видимо, это связано с нагревом самого
кристалла при выполнении различных операций, т.к. при этом растет
потребляемый ток. Также замечено, что реальное время преобразования
гораздо меньше 750 мс, и составляет около 400 мс (выяснение зависимости
от измеряемой температуры или напряжения питания не проводилось).
Если от устройства требуется максимально быстрая реакция на изменение
температуры, имеет смысл после запуска преобразования опрашивать
регистр статуса на предмет единицы в MSB (done). При использовании
стандартной библиотеки CodeVision ds1621.h это будет выглядеть так:

while ((ds1621_get_status(chip) & 0x80)==0);

Впрочем, читать регистр статуса можно и самостоятельно, без библиотеки,
но опять-таки непрерывное обращение к датчику вызывает некоторое
завышение измеренной им температуры.
**********************************************************************/

void ds1621_init(void)
{
i2c_start();
i2c_write(0x90|(01)); i2c_write(0xAC);
i2c_write(0b00000001); //в LSB конфигурационного байта пишем 1 - преобр. по запросу.
i2c_stop();

i2c_start();
i2c_write(0x90|(01));
i2c_write(0x22); // остановка преобразования
i2c_stop();
}

void ds1621_start(void)
{
i2c_start();
i2c_write(0x90|(01));
i2c_write(0xEE); // старт преобразования
i2c_stop();
}

int ds1621_read()
{
unsigned char i2c_address;
int read_temp;
float b, cpc, cr;

//читаем count_per_c
i2c_address=0x90|(01);
i2c_start();
i2c_write(i2c_address);
i2c_write(0xa9);
i2c_start();
i2c_write(++i2c_address);
cpc=i2c_read(0);
i2c_stop();

//читаем count_remain
i2c_address=0x90|(01);
i2c_start();
i2c_write(i2c_address);
i2c_write(0xa8);
i2c_start();
i2c_write(++i2c_address);
cr=i2c_read(0);
i2c_stop();

//читаем старший байт температуры
i2c_address=0x90|(01);
i2c_start();
i2c_write(i2c_address);
i2c_write(0xaa);
i2c_start();
i2c_write(++i2c_address);
read_temp=i2c_read(0);
i2c_stop();

b=read_temp-0.25+(cpc-cr)/cpc; //вычисляем температуру

return b*10;
}

/* end of file */
[/b]

PS: Как есть может работать только с одним датчиком (с нулевым адресом). Но добавить передачу адреса датчика не так уж и сложно.

 

Спасибо! Сохранил в закрома (или в анналы ), когда-нибудь наверняка пригодится

 

DS1621 точность если не ошибаюсь 0,5 градуса с погрешностью (плюс минус 1) снимать с него десятые доли бездумно, все равно неправильно будет )))

 

Если ввести внешнюю поправку (калибровку), думаю, будет все в порядке. Там наверняка разброс параметров такой, а относительное изменение точности по диапазону в процессе работы небольшое.

 

В моем случае было важно отслеживать относительное изменение температуры (для правильной работы алгоритма регулирования) С уважением, Николай.

 

Николай Брагин: b=read_temp-0.25+(cpc-cr)/cpc; //вычисляем температуру
А вот как перевести часть после запятой в двоично-десятичный вид , чтоб вывести её на индикатор, предположим хватит 1-го знака после запятой.
Что-то я не смог справиться с этой арифм. задачкой, вернее справился тупо- сделал таблицу из 16 HEX-значений и соотв. им десятичных.
У DS18B20 попроще- никаких формул не надо, дробная часть в 4 млад. разрядах LS Byte, но как ей BIN-BCD сделать что-то никак не въеду.
Например, температура 25.125 град. Датчик выдаст 0192h. 19h переводится в 25 легко, как 2h перевести в 125?
Я передаю значение температуры на комп, там никаких проблем,- (LSByte & 0x0F)/16 и прибавить к целой части, а вот на уровне контроллера что-то я поплыл.

 

Честно говоря, не озадачивался. Так как использовал форматированный вывод, и в последовательный порт, и на LCD.

 

Понимаю, что уже не нужно ... но может кто поиском себе найдет.
Нашел на одном из форумов.
Преобразование данных ds18b20 в десятичный вид. (температура 36,6 ... получаем 366)

При 12 битовой точности получаем температуру в 0,0625 градусах, что бы получить с точностью до десятых нам нужно умножить полученное число на 0,625 .
t = (ds_data>>1)+(ds_data>>3) Как мне понравилось это решение!

ds_data/2 + ds_data/8 = (4*ds_data)/8 + ds_data/8 = ds_data * 5/8 = ds_data*0.625

Если используете другое расширение, то нужно подобрать другие сдвиги - пробовал - получается.

Если работает с отр. температурами, то нужно запоминать и восстанавливать знак (+/-) числа.

 

AndryG:
"Влад Князев.Умножение без умножения"- толковая статья про умножение на константу, как раз у вас -это частный случай :
http://www.onembedding.com/hints/algorithms/mwom/

 

Здорово! Спасибо за ссылку!