ds1821 help!!!

Loading thread data ...

Hello, Alexander Panasovsky! You wrote in conference fido7.ru.embedded to All on Tue, 27 Dec 2005 21:58:54 +0300:

AP> Hеобходимо считать данные о температуре с датчика DS1821 AP> (именно с этого т.к. AP> он недорогой и у него нужная погрешность при измерении AP> температуры тела человека) и вывести их на ЖКИ (МЕЛТ10-Т7). AP> Проблемма состоит в вычислении температуры. Она вычисляется по AP> формуле:

AP>

AP> temperature=temp-0.5+(COUNT_PER_C-COUNT_REMAIN)/COUNT_PER_C;

AP> Число получается дробное. Точность нужна до десятых причем с AP> округлением а не с обрезанием. Я придумал вот как:

Зачем вообще считать с плавающей точкой? Умножь все на 256 и считай в целых, в конце смасштабируешь. Кстати точность у этих датчиков маловата для измерения температуры тела...

dima

formatting link

Reply to
Dmitry Orlov

Tue Dec 27 2005 20:58, Alexander Panasovsky wrote to All:

AP> Может ли кто нибуть придумать алгоритм получше ибо этот при компиляции AP> winavr становится жирным. Желательно бы использовать AT90S2313, но при AP> моем варианте вся программка вместе с приведенным ниже куском в него еле AP> влазит (1,9кб):((, а ее еще апгрейдить и апгрейдить... С моим вариантом AP> нужно брать мегу, но плата уже разведена для AT90S2313.

AP> Hеобходимо считать данные о температуре с датчика DS1821 (именно с этого AP> т.к. AP> он недорогой и у него нужная погрешность при измерении температуры тела AP> человека) и вывести их на ЖКИ (МЕЛТ10-Т7). Проблемма состоит в вычислении AP> температуры. Она вычисляется по формуле:

AP> temperature=temp-0.5+(COUNT_PER_C-COUNT_REMAIN)/COUNT_PER_C;

AP> Число получается дробное. Точность нужна до десятых причем с округлением AP> а не с обрезанием.

Плавающая точка нужна, в действительности, редко когда. А часть libc её реализующая имеет немерянный размер обычно. Потому и не влазит. Там ещё плавающий printf небось цепляется. Тоже тяжёлый.

Я у себя сделал так: температуру, считываемую из термометра, домножаю сразу на 256. В градусах. Так она хранится, так всё и считается. Диапазон -120 -- +120 вполне умещается в 16-разрядном int с точностью до 1/256 доли градуса. Выводится примерно так:

unsigned ta = abs(temp) + 1; /* 256*0.005 = 1.28 */ sprintf(buf, "%c%d.%2.2uC", /* знак */ (temp<0 ? '-' : '+'), /* целая часть */ ta>>8, /* дробная часть */ (100*(ta&0xff))>>8) );

Видно, что операции деления на 256 -- на самом деле сдвиги, из тяжёлых вычислений только умножение на 100. При вводе всё-таки использую плавающую точку -- разбирать вручную строки описываемые регулярными выражениями вида "^[0-9]*([.,][0-9]*)?([eE][+-]?[0-9]*)?$" нудно как-то...

Температура, считанная из термометра, преобразуется во внутренний для программы формат таким образом:

temp = \ ((((0xff00|scratch.temp_msb)<<8)|scratch.temp_lsb)<<7) - (256/4) \ + 256*(unsigned)(scratch.cpc-scratch.remain)/scratch.cpc;

где scratch описывается такой структурой:

struct scartch { UFAST temp_lsb, temp_msb, TH, TL, R0, R1, remain, cpc, crc; };

это scratch-буфер из даташита.

AP> temperature=temp-0.5+(COUNT_PER_C-COUNT_REMAIN)/COUNT_PER_C; AP> //выделяю сотни, десятки, единицы и сотые доли AP> out[6]=temperature/100; AP> out[7]=(temperature-out[6]*100)/10; AP> out[8]=temperature-out[6]*100-out[7]*10; AP> temperature=floor((temperature-out[6]*100-out[7]*10-out[8])*10+0.5); AP> out[9]=temperature; AP> //там дальше out[] ->это цифры, который выводятся на индикатор с AP> //этим проблем нет

Изобретаешь самодельный printf? В любом случае плавающую точку лучше выкинуть.

Reply to
Kirill Frolov

Wed Dec 28 2005 12:31, Kirill Frolov wrote to Alexander Panasovsky:

KF> temp = \ KF> ((((0xff00|scratch.temp_msb)<<8)|scratch.temp_lsb)<<7) - (256/4) KF> \ KF> + 256*(unsigned)(scratch.cpc-scratch.remain)/scratch.cpc;

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

Reply to
Kirill Frolov
Reply to
Alexander Panasovsky
Reply to
Alexander Panasovsky
Reply to
Anatoly Mashanov

Hello, Alex Gavrikov! You wrote in conference fido7.ru.embedded to Alexander Panasovsky on Thu, 29 Dec

2005 21:38:28 +0300:

AG> Индикация с точностью полгpадуса - для теpмометpа туловища AG> более чем достаточно, думаю. Hет опеpаций деления и пpочих

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

AG> жиpностей типа пpинтф.

А вот они действительно совершенно лишние, что при точности в полградуса, что половине десятой градуса.

dima

formatting link

Reply to
Dmitry Orlov

Wed Dec 28 2005 23:08, Alexander Panasovsky wrote to Kirill Frolov:

KF>> unsigned ta = abs(temp) + 1; /* 256*0.005 = 1.28 */ KF>> sprintf(buf, "%c%d.%2.2uC", KF>> /* знак */ (temp<0 ? '-' : '+'), KF>> /* целая часть */ ta>>8, KF>> /* дробная часть */ (100*(ta&0xff))>>8) KF>> );

AP> Большое спасибо - то что нужно. Я все таки не все понял: как происходит AP> округление, или в этом примере его нет?

round(a) == floor(a+0.5). 0.5 -- это, в действительнсти, 1.28, поэтому берётся просто единица.

AP> ЗЫ: А где можно почитать про функции printf для AVR? Буду благодарен AP> ссылке в интернете.

formatting link

Reply to
Kirill Frolov

Wed Dec 28 2005 23:08, Alexander Panasovsky wrote to Kirill Frolov:

AP> ЗЫ: А где можно почитать про функции printf для AVR? Буду благодарен AP> ссылке в интернете.

Да, самодельный integer_to_string на языке C принципиально невозможно написать, если только у МК не (аппаратной) инструкции деления. У AVR начиная с каких-то есть. А иначе только в ассемблере.

Reply to
Kirill Frolov

Hello, Alexander Panasovsky! You wrote in conference fido7.ru.embedded to Dmitry Orlov on Wed, 28 Dec 2005 23:15:21

+0300:

AP>>> temperature=temp-0.5+(COUNT_PER_C-COUNT_REMAIN)/COUNT_PER_C;

AP>>> Число получается дробное. Точность нужна до десятых причем с AP>>> округлением а не с обрезанием. Я придумал вот как:

DO>> Зачем вообще считать с плавающей точкой? Умножь все на 256 и DO>> считай в целых, в конце смасштабируешь. Кстати точность у DO>> этих датчиков маловата для измерения температуры тела...

AP> Тобишь сделать как я привел ниже?

AP> uint16_t temperature,COUNT_PER_C,COUNT_REMAIN; AP> uint8_t temp; AP> // AP> //считавание // AP> temperature=(uint16_t)(temp*256)-(0.5*256)+(uint16_t)((COUNT_ AP> PER_C-COUNT_REMAIN )*256)/COUNT_PER_C;

Да, в таком духе.

dima

formatting link

Reply to
Dmitry Orlov

Hello, Kirill Frolov! You wrote in conference fido7.ru.embedded to Alexander Panasovsky on Fri, 30 Dec

2005 09:18:38 +0000 (UTC): AP>> ЗЫ: А где можно почитать про функции printf для AVR? Буду AP>> благодарен ссылке в интернете.

KF> Да, самодельный integer_to_string на языке C принципиально KF> невозможно написать, если только у МК не (аппаратной) KF> инструкции деления. У AVR начиная с каких-то есть. А иначе KF> только в ассемблере.

Не понял, какая связь С с наличием каких-то инструкций. Нет инструкции, есть функция в rtl.

dima

formatting link

Reply to
Dmitry Orlov
Reply to
Vladimir Vassilevsky
Reply to
Alex Mogilnikov
Reply to
Alexander Panasovsky
Reply to
Dmitry Krivetskov

Hello, Alex Gavrikov! You wrote in conference fido7.ru.embedded to Dmitry Orlov on Sat, 31 Dec 2005 01:49:23

+0300:

AG>>> Индикация с точностью полгpадуса - для теpмометpа туловища AG>>> более чем достаточно, думаю. Hет опеpаций деления и пpочих

DO>> Вообще-то обычный медицинский ртутный градусник имеет DO>> точность около DO>> 0.1 градуса и разрешение примерно вдвое выше (полделения DO>> отчетливо

AG> Точно. Сейчас нашел в аптечке этот девайс - 0,1 AG> гpадус/деление.

AG> Согласен, что полгpадуса туповато будет. 36,6 здоpовый AG> человек, 37,0 гpадусов уже больной.

AG> Инициатоp тpеда явно пpомахнулся с выбоpом DS1821. AG> DS1624 пpедпочтительнее.

Достичь такой _точности_ и стабильности полупроводниковым градусником врядли удастся. Замечал, что дешевые цифровые градусники показывают весьма неточно, хотя конечно безопасней ртутных.

dima

formatting link

Reply to
Dmitry Orlov

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.