Термометр на LM75AD

Данный пост написан в связи с огромным количеством вопросов по термометру на ds18b20, о котором я писал ранее. Вопросы были в основном где купить датчик и чем его можно заменить. Если не требуется большая точность измерений температуры и использование  корпуса soic с 8-ю ногами  приемлемо, то можно смело лепить термометр на датчике LM75AD. Это пожалуй самый дешевый цифровой термодатчик из всех что мне удалось найти в интернете. Но несмотря на его дешевизну и распространённость, он имеет неплохие характеристики и некоторые фишки, которых нет у других термодатчиков.  Ну и конечно же ему присущи некоторые недостатки. Обо всем этом пойдет рассказ ниже.

А нафига вообще сдался цифровой термодатчик? Может проще взять какой нибудь терморезистор, и приделать его к контроллеру? Такой же вопрос возник у меня, и я решил заюзать терморезистор KTY81/120. Редкостный отстой скажу сразу. Зависимость сопротивления от температуры не линейная — вот главный минус. Два одинаковых датчика дают разные показания +/- 2 градуса. Короче, ну его в пень. Да к тому же  для такого датчика еще ведь и АЦП нужен, а он есть не во всех контроллерах, да и иногда все его каналы задействованы под другие нужды. А для АЦП нужен нормальный источник опорного напряжения, а это еще одна лишняя деталюха. Да и еще всё это дело нужно правильно развести на плате. Короче сплошные минусы. Ну кроме цены конечно. LM75AD на пять рублей дороже KTY81/120 =) Ценовая разница ничтожна, а плюсов у LM75AD целый  вагон:

1) Хороший диапазон измеряемых температур ( от -55 °C до +125 °C)
2) Не нужен АЦП
3) При достижении заданной температуры может дрыгнуть ногой
4) На одну шину i2c можно подключить до восьми таких датчиков
5) Есть режим энергосбережения

Распиновка LM75AD

Конечно soic  корпус не всегда удобен, в отличии например от TO-92 в котором выпускаются датчики ds18b20 и ему подобные, но и его при желании можно прикрепить куда надо. Главное проявить немного фантазии. Например, я этим датчиком измеряю температуру аккумуляторов при зарядке. Прицепил его очень просто: В дне аккумуляторного отсека сделал дырку, и суперклеем намертво закрепил его там.

Теперь  посмотрим как работать этим датчиком. Как и у любого устройства с интерфейсом i2c, у этого термометра есть свой адрес, по которому контроллер обращается к нему. За счёт трёх входов (А0,A1,A2) можно задать для микросхемы три последних бита адреса. Благодаря этому можно подцепить к одной шине сразу 8 таких датчиков. Если требуется еще больше, то можно организовать программный i2c, и повесить остальные датчики на него. Адрес LM75AD выглядит так: 1 0 0 1 A2 A1 A0 Алгоритм чтения и записи в регистры микросхемы, ни чем не отличается от микросхемы памяти 24Lхх. Об этом я писал ранее и повторяться не буду. Регистры микросхемы распределены в памяти следующим образом:

LM75AD

Из таблицы видно что по нулевому адресу расположено то что нас интересует в первую очередь — температура датчика. Температура занимает 11 бит памяти и в один байт разумеется не поместилась. Старший байт регистра температуры содержит целую часть температуры, а младший байт — дробную, причем биты в младшем байте выровнены по левому краю (см. рисунок)LM75AD

Для вычисления значения температуры нужно применить следующий мозгоразрывный алгоритм:

Если седьмой бит старшего байта температуры равен 0 тогда
Температура=СодержимоеРегистра * 0.125
Если седьмой бит старшего байта температуры равен 1 тогда
Инвертируем биты  регистра температуры потом считаем по формуле
Температура=-(СодержимоеРегистра+1) * 0.125
Первая формула была явно указана в даташите, а вот надо вычислением отрицательной температуры пришлось пораскинуть мозгами. Это иногда полезно =)

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

LM75AD Config Bits

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

SHUTDOWN — Бит управления питанием датчика. Если выставить этот бит в единицу, то датчик прекратит измерять температуру. При считывании, датчик постоянно будет выдавать последнюю замеренную температуру. Использовать этот бит очень выгодно в устройствах с батарейным питанием, где каждый миллиампер потребляемого тока на счету. В режиме энергосбережения данный датчик потребляет всего ничего: 4 мка (по результатам моих измерений).

OS_COMP_INT — х.з. чё такое. Из даташита назначение сего бита я понял слабо. Путём научного тыка, было выяснено что он задает поведение вывода OS. Когда этот бит сброшен, то на выводе OS, (в случае превышения температуры заданного порога) появится постоянное напряжение логической единицы или нуля (в зависимости от настроек). Если же бит установлен, то при превышении температуры определенного уровня (задается спец регистром)  на ноге OS появится всего лишь короткий импульс. Но эта информация пока не проверенна по техническим причинам (спалил вывод OS)

OS_POL — Позволяет задать активный логический уровень ноги OS. Если бит сброшен — активный ноль. Если установлен — то активный уровень это логическая единица.

OS_F_QUE — эти два бита определяют сколько раз температура должна превысить заданный уровень, чтоб датчик активировал ногу OS. Доступно шесть комбинаций:
OS_F_QUE_1=0 OS_F_QUE_0=0 — сработает сразу
OS_F_QUE_1=0 OS_F_QUE_0=1 — после двух превышений
OS_F_QUE_1=1 OS_F_QUE_0=0 — после четырёх
OS_F_QUE_1=1 OS_F_QUE_0=1 — после шести

Осталось еще два регистра. Они задают температуру при которой срабатывает нога OS и при какой температуре эта самая нога возвращается в исходное состояние. Оба регистра 2-х байтные и имеют такую структуру:

При включении питания регистр порога температуры равен 80 градусов, а регистр гистерезиса 75 градусов. Следует помнить что регистр порога должен быть больше регистра гистерезиса.

Как говорится соловья баснями не накормишь,  поэтому от теории переходим к практике. Вооружившись отладочной платой я сотворил термометр на микроконтроллере Atmega48 и 4-х разрядном семисегментном индикаторе. Чтоб не терять времени на разработку, решил воспользоваться преимуществами языка высокого уровня. Памяти мне не жалко, быстродействие не критично. Из языков высокого уровня мне полюбился микропаскаль, его то и заюзал. Схема термометра выглядит так:

ВНИМАНИЕ! Конденсатор параллельно питанию датчика тут не для прикола. Его нужно ставить обязательно. Иначе датчик будет вместо нормальной температуры возвращать какой-то треш. Расположить его на плате необходимо как можно ближе к выводам питания датчика. Других замечаний по разводке платы нет. Программа особо не тестировалась, особенно это касается отрицательных температур. Поэтому, если на индикаторе отображается что-то не то, тогда пишем багрепорт в комменатах. Или можно поправить исходник самому. Но я думаю что в этом вряд ли возникнет необходимость. Фьюзы микроконтроллера должны быть настроены так:

И еще небольшое замечание по поводу вывода OS. Его нагрузочная способность очень мала. Видимо из-за этого у меня сгорел этот вывод, когда я подключил к нему светодиод через резистор на 200 ом. Теперь, когда там появляется логическая единица, вместо пяти вольт там около одного вольта. Будьте осторожны, поставьте транзисторный ключ в случае необходимости.

Скачать прошивку термометра
Скачать микропаскаль

Термометр на LM75AD: 53 комментария

    1. Микропаскаль понравился своим синтаксисом, безглючностью компилятора и удобной средой разработки.
      Плюс там есть куча библиотек есть на все случаи жизни. Жалко только что нельзя прям из него контроллер прошивать как в студии. Микропаскаль увы не поддерживает атмеловские программаторы.

    1. А фиг знает как он называется. Пойдет любой 4-х разрядный семисегментный светодиодный индикатор с общим катодом. Если будет общий анод тоже не страшно. прошивку переделать легко.

  1. спасибо, ссылку сразу не заметил((
    если ещё подскажите как его запрограммировать, буду безкрайне благодарен…
    только подоступнее по возможности…

    нашёл вот такой программатор http://www.getchip.net/posts/delaem-com-programmator-dlya-avr-mikrokontrollerov/
    (самый экономичный вариант)

  2. Хотел повторить твою конструкцию, купил индикатор led-индикатор CC56-11GWA. Не могу теперь понять каким макаром его включить к меге, 32 ноги и каждый разряд управляется сам по себе… чую нужен какой-то преобразователь на какой-нибудь микросхеме типо КР155… подскажи, как быть в такой ситуёвине…

    1. Ничего страшного этот индикатор подойдёт. Просто соедини одинаковые сегменты у всех четырёх разрядов между собой. В результате у тебя получится такой же индикатор как у меня на схеме. С 12-ю выводами.

  3. знаю, что уже достал((
    но последний вопрос))

    можно ли как-нибудь прошивку преобразовать в с++
    задание у меня написать код на этом языке, дрогой преподаватель не возьмёт

    а сам чайник и написать не смогу((

  4. Блин, наебался, когда печать разводил… сцук…
    Распиновка в схеме для DIP корпуса… купил мегу в TQFP корпусе… хорошо, что в даташит залез….
    сцук… опять переразводить… будьте внимательны!

  5. Разводить вообще нехер. Но люблю порядок, поэтому макетки в топку и делаем по человечески. Самая жопа наступила с индикатором в 36-выводов, где и замкнуть и на контроллер подать. Кстати, рекомендую kingbright cc56-12 индикатор, там все запараллелено внутри.
    Однако, Медвед, ты пожалуйста указывай в следующий раз для какого корпуса распиновка контроллера… шоб не влететь снова так…

  6. Попробовал запустить Вашу программу на ATmega16 и посмотрел осциллографом состояние SDA и SCL. На линии SCL были импульсы, а на SDA просто высокий уровень. Подскажите в чем проблема?

  7. **************
    …Если седьмой бит старшего байта температуры равен 1 тогда
    Инвертируем биты регистра температуры потом считаем по формуле
    Температура=-(СодержимоеРегистра+1) * 0.125
    Первая формула была явно указана в даташите, а вот надо вычислением отрицательной температуры пришлось пораскинуть мозгами. Это иногда полезно =)
    **************

    Такое представление отрицательных чисел называется «представление числа в дополнительном коде». Получается вычитанием из нуля модуля числа. Используется поголовно всеми процессорами. Позволяет уйти от одной из операций сложения или вычитания и тд…

  8. Альтернативная замена датчика (улучшенная) — AD7416

    Резисторы для подтяжки на 10к надо на I2C.
    Измерение от −40°C до +125°C
    Точность: +-2 градуса в диапазоне от -25 до 100 градусов.

    Распиновка такая же.

  9. Здравствуйте.

    Я конечно понимаю, что тема давняя, но все же… С работой датчика разобрался, и эта статья конечно помогла, в плане описания регистров, спасибо большое. Правда, порог срабатывания это 03h, а гистерезис 02h (в статье наоборот), ну да не в этом дело.

    Мне вот что интересно, а этот датчик не способен работать сам по себе? Пороги-то я зашил, с МК все работает прекрасно, а вот один не хочет… Глупость, наверное, но вроде как запуск измерения ему ведь не нужен, мы же просто забираем результат…

      1. В том и дело… О, определил в чем дело. Что-то раньше такое в голову не пришло… Прогрел феном и сработал вывод. Порог по умолчанию 80С. Так они что, не сохраняются, штоле? :(

          1. Не, ну когда есть питание, то конечно сохраняются. :))) Но я-то говорил про работу без МК. Можно конечно на ходу отключить МК, так будет работать до первого отключения питания. :)

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

  10. Пару копеек в защиту KTY81

    Если читать даташит LM75A то мы видим, что погрешность температуры у него выше чем у KTY81/120.
    Но зачем покупать KTY81/120, если можно купить за такую же цену KTY81/222 у него погрешность в 2 раза меньше чем в LM75A

    Итого, погрешность:
    LM75A от -55…+125ºС — 3°С
    KTY81/120 -55…+150ºС — 2,54°С
    KTY81/222 -55…+150ºС — 1,27°С

    К тому же у KTY81 куда как удобнее корпус.

    Т.е. они примерно равны, смотря куда применять датчик.

    1. I2C_Init(100000);
      I2C_Start();
      I2C_Wr(0x90);
      I2C_Wr(0x00);
      I2C_Repeated_Start();
      I2C_Wr(0x91);
      A = I2C_Rd(0);
      B = I2C_Rd(0);
      I2C_Stop();

      if ((A&0x80)==0x80){minus = 1;} else minus = 0;
      x=0;
      x=x|A;
      x=x&0x7F;
      x=x<>5;
      if (minus)
      {
      temp = ~x;
      temp = temp & 0xFF;
      temp2 = temp;
      temp = (temp2+1) * 0.125;
      }
      else {
      temp = temp & 0x3F;
      temp = x * 0.125;
      }

Добавить комментарий