Термометр на датчике se97b и avr-микроконтроллере

Простой термометр на LCD (DS18B20)

0Спам64 Никополо   (09.03.2013 02:07)смотрите ответ к сообщению 7, на предыдущей страницы, скорее всего, неправильно выставлены фьюзы (не отзеркальте). Настройка фьюзов на стр.30 тех.док. В протеусе они выставляются при двойном щелчке по микроконтроллеру, в CVAvr в Chip Programmer'e справа снизу, в AVR Studio они выставляются и программируются также в специальной вкладке.

0Спам58 Artur   (13.11.2011 15:27)Есть ли датчики с диапазоном до +250 или +300? или как прицепить терморезистивный датчик?

0Спам59 HiSER   (13.11.2011 15:45)Генератор тока + ОУ и снимать значения с помощью ADC.

0Спам60 Artur   (13.11.2011 21:12)кажется должно быть проще. я видел продаются готовые с диапазоном -40 +250 только вот хочу сам сделать

0Спам61 HiSER   (13.11.2011 23:18)Вариант, как делитель VCC-[]-SIG-[TERM]-GND, SIG на ADC.Ну и точность соответствующая…

0Спам56 serj   (03.08.2011 12:49)Подключил 4-ре датчика DS18B20 к Atmeg16. Сами датчики определяются, считываются в первом цикле. Во втором цикле и далее первый датчик выдает -9999. Если вывожу только три датчика, то первый показывает правильную температуру. Также программа работает если вместо третьего вывожу четвертый датчик. Можно одновременно выводить на LCD (WH1604) только три датчика. В чем причина? Программа написана в CVAVR с использованием стандартных библиотек. Датчики вывожу (и считываю) как float.

0Спам57 HiSER   (03.08.2011 20:47)что за привычка писать проблемы в комментарии?для этого есть форум…

0Спам54 Merlin   (14.07.2011 13:09)А инклюды, библиотеки тот исходник безполезен без них

0Спам55 HiSER   (14.07.2011 13:10)Для твоего сведения это стандартные библиотеки CVAVR.

0Спам52 Merlin   (13.07.2011 10:10)хм, а где собственно исходники?

0Спам53 HiSER   (13.07.2011 10:40)по середине статьи!

0Спам51 lameruga3957   (19.06.2011 20:22)Залит мой проект термометра с точностью 0.1 градусов на DS18B20 и дисплее Nokia3310 на http://zalil.ru/31294573

0Спам50 lameruga3957   (18.06.2011 13:42)Что-то я не вижу, как прицепить тут файл, подскажите,кто знает.

0Спам49 serj   (17.06.2011 20:48)Объясните мне плиз эту строку sprintf(lcd_buffer,”t=%i.%uxdfC”,temp,temp%1);здесь выводится температура с дробным значением? Почему нельзя объявить температуру как float и выводить как float через функцию sprintf()?

0Спам47 green_noob   (30.05.2011 22:04)в общем пробую занимать подобными вещами 1й раз и уже при моделировании в протеусе выдает ошибки: 1. AVR: program property is not defined. 2. real time simulation failed to start. так же интересует вопрос по поводу прошивки, не самой программы, а именно “запихивании” её в модель с последующей проверкой.подозреваю что задаю очень идиотские вопрос, но уж простите…

0Спам48 HiSER   (30.05.2011 22:06)в свойствах модели надо выбрать файл с прошивкой и ошибка пропадет…

0Спам45 green_noob   (30.05.2011 20:55)здраствуйте товарищи! нужна помощь. нужно сорать схему в протеусе цифрового термометра, ну и програмку соответственно…пробовал сам делать, но т.к. опыта 0, нифига не получается… заранее благодарен, как можно подробное описание приветствуется.

0Спам46 HiSER   (30.05.2011 20:56)что не получается то?

Источник: http://my-avr.at.ua/publ/1-1-0-10

Термометр на датчике SE97B и AVR-микроконтроллере

Устройство и схема повербанка

Паяльник TV

3 жилийн өмнө

Фазировка трансформаторов

Паяльник TV

3 жилийн өмнө

$10 QUEER EYE TRANSFORMATION (w/ Jon Cozart)

Smosh

2 өдрийн өмнө

Asian Bachelorette 2

Wong Fu Productions

7 өдрийн өмнө

Have you ever seen an atom?

nature video

5 жилийн өмнө

Как прошить микроконтроллер AVR.

Ruselectronic

3 жилийн өмнө

Лучшие стабилизаторы напряжения

Александр Коваленко

4 жилийн өмнө

✅Самодельный небесный фонарик с зажигалкой

KREOSAN

5 жилийн өмнө

электропривод для окна своими руками

имя фамилия

4 жилийн өмнө

Создание макросов в Sprint Layout 6

Паяльник TV

4 жилийн өмнө

Измеритель ESR конденсаторов на базе мультиметра

Паяльник TV

5 сарын өмнө

Умощненная схема лабораторного блока питания

Паяльник TV

4 жилийн өмнө

1-Day Project: Build Your Own Arduino Uno for $5

Julian Ilett

3 жилийн өмнө

Термометр на МК Attiny 2313

Evgenyi Baranetskyi

4 жилийн өмнө

Портативная колонка своими руками

JeyMiks

6 жилийн өмнө

Термометр на Attiny 2313 и LCD 16×2

Гацко Production

4 жилийн өмнө

Видеокурс по AVR микроконтроллерам – Урок 8

Паяльник TV

4 жилийн өмнө

Мопед из бензопилы(Moped from chainsaw)

TomRaily

6 жилийн өмнө

Высоковольтный генератор

Паяльник TV

4 жилийн өмнө

Зарядка Li-ion/Li-pol аккумуляторов (автоматическое)

AKA KASYAN

4 жилийн өмнө

Робот своими руками на Arduino.

Andrey Gilenko

5 жилийн өмнө

How to Arduino #2 – use a 1602 LCD display

Garage Geek Guy

4 жилийн өмнө

Цифровой USB-термометр

Чип и Дип

8 жилийн өмнө

Система доступа на RFID картах

Паяльник TV

4 жилийн өмнө

Часы термометр на MAX7219 + радио датчик температуры.

DIY chаnnеl

Жилийн өмнө

DS3231

Паяльник TV

4 жилийн өмнө

Переделка компьютерного блока питания

AKA KASYAN

3 жилийн өмнө

STH0014, встраиваемый цифровой термометр с …

Чип и Дип

6 жилийн өмнө

ФОНАРИК БЕЗ БАТАРЕЕК СВОИМИ РУКАМИ

Sergei Kim

4 жилийн өмнө

Распаковка модуль часов DS3231

Все сами

3 жилийн өмнө

Цифровой термометр на микроконтроллере ATmega8

ПРОМО LIFE

Жилийн өмнө

Устройство для экономии электроэнергии

AKA KASYAN

4 жилийн өмнө

Самодельный цифровой термометр и часы.

Игорь Круч

3 жилийн өмнө

Печатные платы в домашних условиях

Паяльник TV

4 жилийн өмнө

Переделка ЗУ для мобильника

Паяльник TV

4 жилийн өмнө

Смотрим все! Лабораторный БП с нуля за один вечер!

AKA KASYAN

4 жилийн өмнө

Ночник на микроконтроллере

Паяльник TV

4 жилийн өмнө

Самодельные часы на Atmega8

Igorek Kol

4 жилийн өмнө

Лазерная резка металла. Роботизированный комплекс.

NewlaserRu

3 жилийн өмнө

Источник: https://mnfilm.net/v-%D1%82%D0%B5%D1%80%D0%BC%D0%BE%D0%BC%D0%B5%D1%82%D1%80-%D0%BD%D0%B0-%D0%B4%D0%B0%D1%82%D1%87%D0%B8%D0%BA%D0%B5-se97b-%D0%B8-avr-%D0%BC%D0%B8%D0%BA%D1%80%D0%BE%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D0%BB%D0%B5%D1%80%D0%B5-uProBfz31WU.html

Термометр на датчике SE97B и AVR-микроконтроллере

Думаю, многие могут могут найти у себя в закромах отголоски щедрости компании NXP semiconductors в виде бесплатных образцов электронных компонентов. Раздавали они и красиво оформленные наборы I2C микросхем для различных классов приложений.

В одном из таких наборов (computer applications) имелись датчики температуры под маркировкой SE97BTP. Помимо датчика температуры эта микросхема выполняет функции EEPROM памяти.

Так вот, если есть такая микросхема, то почему бы не попробовать ее использовать где-либо в своих разработках? Мельчайший корпус датчика HWSON8 позволит без труда встроить термометр в любое устройство, ну или почти в любое.

Размер корпуса HWSON8 термодатчика SE97B составляет 2 на 3 миллиметра.

Рассмотрим эту микросхему и ее характеристики. Как указывалось выше, это не только датчик температуры, но и память EEPROM. Последнее нас не очень то и волнует. SE97B позиционируется производителем как температурный сенсор для DDR модулей памяти. Объем EEPROM памяти составляет 256 байт. Вся эта память разделена на 2 части – 128 байт имеют защиту от записи, остальные 128 байт не имеют защиты.

Интерфейс передачи данных используется I2C. При этом микросхема имеет три адреса – один для обращения к регистрам термометра, остальные два для обращения к памяти EEPROM с защитой от записи и без нее. При этом адрес микросхемы в общем учитывает состояние выводов A0, A1, A2 – подключены к земле или к питанию и в зависимости от этого в адрес ставятся единички или нолики в соответствующие места.

 Максимальное разрешение информации о температуры составляет 0,125 градусов Цельсия или 11 бит. Период обновления регистров хранения информации о температуре 0,125 секунды или 8 Гц. Также аналогично температурному датчику LM75 того же производителя имеется вывод EVENT.

Сигнал на этом выводе появляется при условии превышения заданной температуры. В карте регистров имеется верхний и нижний предел срабатывания, отдельно задается гистерезис для этого ввода – 6, 3 или 1,5 градуса Цельсия.

Также может задаваться активный уровень для этого вывода – высокий или низкий уровень.

Характеристики микросхемы температурного датчика SE97B:

  • напряжение питания от -0,5 до 4,3 вольт
  • допустимое напряжение на выводах SCL, SDA, A1, A2, EVENT от -0,5 до 4,3 вольт
  • допустимое напряжение на выводе A0 от -0,5 до 12,5 вольт
  • ​допустимый ток на выводах SDA, EVENT 10 мА
  • точность измерения температуры в диапазоне от 75 до 95 градусов – ±0,5%
  • точность измерения температуры в диапазоне от 40 до 125 градусов – ±1%
  • точность измерения температуры в диапазоне от -40 до +125 градусов – ±2%
  • потребляемый ток 250 мкА
  • частота работы протокола I2C от 0 Гц до 400 кГц
  • 100000 периодов перезаписи памяти EEPROM или 10 лет службы
  • защита от записи памяти EEPROM

По характеристикам четко просматривается заданная область применения датчика температуры – компьютерные приложения, а именно модeли памяти DDR. дело в том, что максимальная точность измерения температуры находится как раз в рабочей области температур компьютерной техники (от 75 до 95 градусов – критический предел рабочей области, который необходимо максимально точно контролировать).

Спустимся с небес высокой технологии компьютерной техники и перейдем к более насущным проблемам – контроля температуры в домашних условиях.

К слову LM75 в диапазоне от -40 до +125 градусов имеет такую же точность, даже чуть хуже – до ±3%, но чуть больший диапазон отрицательных температур.

Так что если бы стоял выбор между LM75 и SE97B, скорее всего бы я выбрал второй датчик, хоть и специфический, но более точный, да и корпус много более мелкий. 

​Таким образом, схема термометра выглядит следующим образом:

Микроконтроллер был выбран Atmega8 за свою широкую распространенность и небольшую цену, а также весь необходимый функционал для построения данной схемы. Данный микроконтроллер можно использовать как в корпусе DIP-28, так и в SMD исполнении в корпусе TQFP-32.

 Резистор R3 необходим для предотвращения самопроизвольного перезапускания микроконтроллера в случае появления случайных помех на выводе PC6. Резистор R3 подтягивает плюс питания к этому выводу, надежно создавая потенциал на нем. Для индикации используется жидко кристаллический (ЖК или LCD) дисплей. Марка дисплея 2004А – 4 строки по 20 символов.

Большой размер дисплея был использован для построения пользовательского шрифта высотой в 4 строки дисплея. При использовании такого шрифта на экран помещается всего 5 символов, зато больших. Этот шрифт можно найти в исходном коде прошивки микроконтроллера, прилагающемся ниже. Переменный резистор R2 необходим для регулировки контраста символов на дисплее.

Вращением движка этого резистора добиваемся наиболее четких для нас показаний на экране. Подсветка ЖК дисплея организована через вывод “А” и “К” на плате дисплея. Подсветка включается через резистор, ограничивающий ток – R1. Чем больше номинал, тем более тускло будет подсвечиваться дисплей. Однако пренебрегать этим резистором не стоит во избежание порчи подсветки.

 Для питания схемы используется микросхема линейного стабилизатора L7805, ее можно заменить на отечественный аналог пяти вольтового линейного стабилизатора КР142ЕН5А, либо применить другу микросхему стабилизатора напряжения в соответствии с подключением ее в схеме (например LM317 или импульсные стабилизаторы LM2576, LM2596, MC34063 и так далее).

Далее 5 вольт стабилизируются другой микросхемой – AMS1117 в исполнении, дающей на выходе 3,3 вольта. Применение второго стабилизатора обусловлено максимальным рабочим напряжением датчика температуры.

Схема была собрана и отлажена на макетной печатной плате для микроконтроллера Atmega8:

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

Логика работы устройства не сложная – извлечение данных по I2C интерфейсу из температурного датчика и вывод их на LCD дисплей с использованием большого шрифта.

Для того, что бы получить данные от датчика необходимо передать условие старта при помощи I2C, далее передать адрес устройства (температурный сенсор) с битом записи, далее передать адрес регистра хранения данных о температуре. Потом, чтобы считать данные из этого регистра, нужно либо передать условие остановки и следом условие старта, либо просто рестарт.

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

Биты 15 – 13 использовать не будем. Биты с 12 по 1 содержат информацию о температуре – целую и дробную часть. Бит 0 зарезервирован и не используется, всегда равен нулю.

Программно все это выглядит на языке Си так:

void Read_temper (void) { i2c_start_cond(); // запуск i2c i2c_send_byte(adr_write); // передача адреса устройства, режим записи i2c_send_byte(0x05); // передача адреса памяти i2c_stop_cond(); // остановка i2c i2c_start_cond(); // запуск i2c i2c_send_byte(adr_read); // передача адреса устройства, режим чтения t1 = i2c_get_byte(0); // чтение MSB температуры t2 = i2c_get_byte(1); // чтение LSB температуры i2c_stop_cond(); // остановка i2c buf1=t1; buf2=t2; temp1=(buf1*16)+(buf2/16); buf2=t2; temp2=buf2*16; temp2=temp2/128; temp2=temp2*5; }

Далее в бесконечном цикле эта функция вызывается и полученная информация выводится на дисплей. Период обновления данных на экране составляет 7,5 секунд. Информация о текущей температуре выводится на экран с разрешением в 0,5 градуса. Учитывается только один бит дробной части.

Для программирования микроконтроллера Atmega8 необходимо знать конфигурацию фьюз битов (скриншот сделан в программе AVR Studio):

К статье прилагается прошивка для микроконтроллера ATmega8, документация на датчик температуры SE97B, исходный код прошивки в программе AVR Studio, печатная плата для модуля SE97B, а также видео работы термометра (при контакте с теплой поверхностью температура возрастает, при прекращении контакта с теплой поверхностью температура медленно понижается).

Скачать список элементов (PDF)

Прикрепленные файлы:

  • 39.hex (19 Кб)
  • 39.rar (52 Кб)
  • SE97B.lay6 (40 Кб)

Источник: http://cxem.gq/mc/mc317.php

Термометр на ATtiny2313 и DS18B20 (ATtiny2313, С)

В Интернете есть куча схем термометров на AVR, но как всегда хочется чего-то своего.. Да и мозги размять тоже следует. Этот термометр был одним из первых моих проектов.

Чего хотелось:

  • минимальные размеры (в разумных пределах)
  • минимальная стоимость
  • простота конструкции
  • высокая повторяемость
  • универсальность (об этом чуть позже)

Что получилось:

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

Схема.

На схеме показан второй вариант включения термодатчика, если он не захотеть работать по однопроводной шине (что встречается очень редко). Обратите внимание, что подтягивающий резистор на 11 выводе должен быть именно 4,7кОм. Уменьшение или увеличение может привести к нестабильной работе датчика в случае включения по однопроводной схеме.

Как видим эта схема отличается от подобных отсутствием транзисторов на управление сегментов. Таким образом схема упростилась на 4 транзистора и 4 резистора, по сравнению с аналогичными схемами.

Тут некоторые скажут: «так нельзя — большая нагрузка на порты!!!». Читаемdatasheet на сей контроллер «DC Current per I/O Pin — 40.0 mA«.

У нас 8 сегментов в каждом символе, по 5 мА каждый — получается 40мА!!!.

Теперь посмотрим графики из того же описания:

Из графиков видно, что ток может достигать и 60 мА и даже 80 мА на пин. Ну не будем увлекаться — нам 5 мА на сегмент (40мА на символ) хватит с головой! Ограничительные резисторы подобраны для получения тока около 5 мА на сегмент. В моей схеме стоят 470 Ом. Яркость сегментов при этом отличная!!! Так, чё-то я увлёкся теорией.

Практика!!!

Печатную плату рисовал исходя их соображений «как можно меньше, но как можно проще». Поэтому она получилась с несколькими перемычками…

На рисунке есть место под кварц — это для небольшой универсальности — у меня было несколько штук AT90S2313, у которых нет внутреннего генератора. КРЕНка применена в корпусе SOT-89.

Защитные стабилитроны BZX79-C5V1 в корпусе DO-35. Конденсаторы в фильтре питания — 10mkF * 16V танталовые (других не нашлось), размера 3528 (SMD-B). Я их обычно не ставлю, а вместо них — 1mkF * 50V размера 1206.

Глюков связанных с питанием не замечено.

Ну и далее фотки платы:

пустая плата, изготовленная «лазерным утюгом»

собранная плата: вид со стороны проводников (не хватает стабилизатора)

вид со стороны элементов (не запаян индикатор)

Далее запаиваем индикатор и программируем:

Проект собран по кускам, что-то из готовых проектов из Интернета, что-то дописано мной… Оригинальной идеей стала динамическая индикация.

Проблема заключалась в том, что во время общения с датчиком температуры DS18B20 возникали моменты, когда «сканирование» индикации останавливалось.

Поэтому обновление индикатора сделано не по прерываниям, а в главном цикле программы, и ещё вставлено кой-где в процедуре общения с датчиком… Плюсом данного способа стала высокая частота обновления, что исключило проблему мерцания.

Чуть не забыл — фьюзы для нормальной работы термометра:

Итак, прошили, включили… Хм… работает!!!

Итак как видим получилось довольно простое (куда уж проще???) устройство, которое по размерам не превышает размер индикатора. Кроме всего ещё и точность высокая: по описанию датчика — «±0.5°C accuracy from –10°C to +85°C». Как показала практика точность гораздо выше — около ±0,1°C. Сверял 10 экземпляров с лабораторным термометром, прошедшим метрологический контроль…

Скачать прошивку для индикатора с ОК(-)
Скачать прошивку для индикатора с ОА(+)
Скачать исходный код на С (CodeVisionAVR)

Автор Юрий. Е-mail: hardlock (пёсик) bk Сайт автора.

Источник: http://elektro-shemi.ru/termometr_na_attiny2313_i_ds18b20_attiny2313_s.html

Примеры CodeVisionAVR

  Подключение одного датчика .

Программная часть. 

Подключим один датчик к микроконтроллеру ATmega8. Программная часть.

Подключаем к основному коду программы заголовочный файл.h

#include

Чтобы начать работать с одним датчиком, достаточно воспользоваться двумя функциями:

Функция инициализации

ds18b20_init( адрес датчика, нижний порог Т, верхний порог Т, разрешающая способность );

функция чтения температуры

ds18b20_temperature( адрес датчика );

Код программы.

#include                                                      // библиотека ввода вывода микроконтроллера#asm  .equ __w1_port=0x18 ;PORTB                                       // сообщаем куда подключен датчик.equ __w1_bit=0#endasm#include                                                         // библиотека работы с 1Wire#include                                                    // библиотека для работы с датчиком ds18b20#asm  .equ __lcd_port=0x12 ;PORTD                                       // сообщаем куда подключён экран#endasm#include                                                            // библиотека для LCD#include                                                        // библиотека задержки#include                                                         // стандартная библиотека вывода символов на экран unsigned char devices;                                                    // переменная в которой количество присоеденённых датчиковint temp;                                                                        // переменная для хранения температуры  unsigned char lcd_buffer[16]; void main(void)                                                              // Declare your global variables here{ PORTB=0b00000000;                                                      // Port B initialization DDRB=0b00000000;                                                      // 0b в таком виде легче представить состояние портовPORTC=0b10000000;                                                      // Port C initializationDDRC=0b00000000;PORTD=0b00000000;                                                      // Port D initializationDDRD=0b00000000;ACSR=0x80;                                                                  // Analog Comparator: Offlcd_init(16);                                                                   // инициилизация LCD, и говорим что он на 16 символовdevices=w1_init();                                                          // ищим датчикиwhile(devices>0)                                                            // бесконечный цикл, если датчик подключон{  temp=ds18b20_temperature(0);                                    // читаем температуру    if (temp>1000){                                                           // если датчик выдаёт больше 1000  temp=4096-temp;                                                        // отнимаем от данных 4096  temp=-temp;                                                               // и ставим знак “минус”}  sprintf(lcd_buffer,”t=%i.%u xdfC”,temp,temp%1);          // записуем в масив показания на экран   lcd_clear();                                                                  // чистим дисплей перед выводом  lcd_puts(lcd_buffer);                                                     // выводим масив на LCD  delay_ms(500);                                                            // ждём 500мс};} 

Проект использования одного датчика ds18b20

Еще один пример если необходимо выводить значение температуры с точностью до одной сотой,

Код программы.

#include                                              // библиотека ввода вывода микроконтроллера#asm  .equ __w1_port=0x18 ;PORTB                               // сообщаем куда подключен датчик  .equ __w1_bit=0                                                   // 1 Wire Bus functions#endasm#include                                            // библиотека для работы с датчиком ds18b20#include                                                // библиотека задержки#define MAX_DS18B20 8unsigned char ds18b20_devices;unsigned char ds18b20_rom_codes[MAX_DS18B20][9];#asm   .equ __lcd_port=0x12 ;PORTD                               // сообщаем куда подключён экран#endasm #include                                                    // библиотека для LCD#include                                                 // библиотека для LCDfloat temper;                                                          // переменная в которой количество int temp_0,temper_fl,min=0;                                   // обьявляем перменныеchar lcd_buffer[16];                                                // масив с данными для экранаvoid temperature(void)                                           // функция по работе с термо-датчиком{temper=ds18b20_temperature(&ds18b20_rom_codes[0][0]);  temp_0=temper;                                                  // отбор целой части от температуры   if(temper 0))                      // установим порог temp_0= temp_0;else{temp_0 =0; } }void main(void)                                                      //основная функция{ char *_str=” c2.at.ua”;                                  //Создаем информ. строку char *_str1=”Tepјoјeїp 0.1 x60C”; PORTB=0b00000000;                                              // «WzAVR «Port B initialization DDRB=0b00000000;                                              // 0b в таком виде легче представить состояние портовPORTC=0b10000000;                                              // «WzAVR «Port C initializationDDRC=0b00000000;PORTD=0b00000000;                                              // «WzAVR «Port D initializationDDRD=0b00000000;ACSR=0x80;                                                          // «Analog Comparator: Offds18b20_devices=w1_search(0xf0,ds18b20_rom_codes);  ds18b20_init(0,-35,35,DS18B20_12BIT_RES);          // переключения термометра в 12 битный режим   w1_init();                                                             // 1 Wire Bus initialization  lcd_init(16);                                                          // Инициализация ЖКИ на 16 символов   lcd_gotoxy(0, 0);                                                  // Переводим курсор на первый символ первой строки   lcd_puts(_str);                                                      // Выводим строку _str на дисплей ЖКИ    lcd_gotoxy(0, 1);                                                  // Переводим курсор на первый символ первой строки   lcd_puts(_str1);                                                    // Выводим строку _str на дисплей ЖКИ   delay_ms(900);                                                    // ждём 900мс    lcd_clear();                                                          // чистим дисплей перед выводом  lcd_init(16);                                                           // «WzAVR « Инициализация ЖКИ на 16 символовwhile (1)                                                                // бесконечный цикл, если датчик подключон  {delay_ms(50);  temperature();                                                     // вызываем функцию температуры  lcd_clear();                                                          // очищаем LCDif(min==1){  sprintf(lcd_buffer,”t=-%u.%u x60C “,temp_0/10,temp_0%10); //вывод отрицательной температуры }else{  sprintf(lcd_buffer,”t=+%i.%d x60C “,temp_0/10,temp_0%10); // вывод положительной}  lcd_puts(lcd_buffer);                                             // вывод на дисплей};}

Проект использования одного датчика ds18b20    с точностью до  0.1°C

Подключение двух датчиков.

При подключении более одного датчика ds18b20 на линию 1-wire, необходимо выполнять чтение ROM каждого датчика, чтоб обращаться к каждому индивидуально. Используя функцию w1_search, производим поиск устройств 1-wire, тем самым выясняем их количество на линии и производим чтение ROM данных каждого датчика:

unsigned char devices;

unsigned char rom_code[2][9];

Код программы.

#include                                              // библиотека ввода вывода микроконтроллера#asm  .equ __w1_port=0x18 ;PORTB                               //сообщаем куда подключен датчик.equ __w1_bit=0#endasm#include                                             //библиотека для работы с датчиком ds18b20unsigned char rom_code[4][9];                                //масив с адресами найденых датчиков#define MAX_DS18B20 8#asm   .equ __lcd_port=0x12 ;PORTD                               //сообщаем куда подключён экран#endasm #include                                                    //библиотека для LCD#include                                                 //библиотека для LCD#include                                                //библиотека задержкиunsigned char i,devices;                                          //переменная в которой количество int temp1,temp2;                                                    //обьявляем перменныеunsigned char lcd_buffer_1[16];                               //масив с данными для экранаunsigned char lcd_buffer_2[16];                               //масив с данными для экрана void main(void)                                                      // Declare your global variables here{ char *_str=” c2.at.ua”;                                  //Создаем информ. строку char *_str1=”2 Tepјoјeїpa 1 x60C”; PORTB=0b00000000;                                              // «WzAVR «Port B initialization DDRB=0b00000000;                                              // 0b в таком виде легче представить состояние портовPORTC=0b10000000;                                              // «WzAVR «Port C initializationDDRC=0b00000000;PORTD=0b00000000;                                              // «WzAVR «Port D initializationDDRD=0b00000000;devices=w1_search(DS18B20_SEARCH_ROM_CMD,rom_code); //определим сколько устройств подключено к шине 1-Wire ACSR=0x80;                                                          // «Analog Comparator: Off ds18b20_init(0,-35,35,DS18B20_12BIT_RES);          // переключения термометра в 12 битный режим   w1_init();                                                             // Wire Bus initialization  lcd_init(16);                                                         // Инициализация ЖКИ на 16 символов   lcd_gotoxy(0, 0);                                                  // Переводим курсор на первый символ первой строки   lcd_puts(_str);                                                      // Выводим строку _str на дисплей ЖКИ    lcd_gotoxy(0, 1);                                                  // Переводим курсор на первый символ первой строки   lcd_puts(_str1);                                                    // Выводим строку _str на дисплей ЖКИ   delay_ms(900);                                                    // ждём 900мс    lcd_clear();                                                          // чистим дисплей перед выводом  lcd_init(16);                                                            // Инициализация ЖКИ на 16 символовwhile(devices>0)                                                     // бесконечный цикл, если датчик подключон  {                                                                           // Place your code here  temp1 = ds18b20_temperature(&rom_code[0][0]);  // читаем температуру с выбранного датчика//if( temp1 > 1000 ) { temp1 = 4096 – temp1; temp1 = -temp1; }  if ((temp1 -60))                        // установим границу диапазон temp1= temp1;else{  temp1 =0;                                                            // если выходит за границу тогда 0}sprintf(lcd_buffer_1,” t%u=%i.%u xdfC “,i+1,temp1,temp1%1);  lcd_gotoxy(0,0);                                                   // указали место на дисплееlcd_puts(lcd_buffer_1); // выводим масив на LCD  temp2 = ds18b20_temperature( &rom_code[1][0] ); //читаем температуру с выбранного датчика  //if( temp2 > 1000 ) { temp2 = 4096-temp2; temp2 = -temp2; }  if ((temp2 -60))                        // установим границу диапазон temp2= temp2;else{  temp2 =0;                                                           // если выходит за границу тогда 0}sprintf(lcd_buffer_2,” t%u=%i.%u xdfC “,i+2,temp2,temp2%1); lcd_gotoxy(0,1);  lcd_puts(lcd_buffer_2);                                          // выводим масив на LCD  delay_ms(30);                                                      // ждём };}

Проект использования двух датчиков ds18b20

Пример проекта где можно подключать датчики “десятками”. 🙂

Код программы.

/*****************************************************CodeWizardAVR Project : Ver. 1.6.0Version : Термометр 1°СDate : 04.02.2012 Company : c2.at.ua Chip type : ATmega8Program type : ApplicationClock frequency : 4,000000 MHz*****************************************************/ #include // библиотека ввода вывода микроконтроллера#asm.equ __w1_port=0x18 ;PORTB //сообщаем куда подключен датчик.equ __w1_bit=0#endasm#include //библиотека для работы с датчиком ds18b20#define MAX_DS18B20 8#asm .equ __lcd_port=0x12 ;PORTD //сообщаем куда подключён экран#endasm #include //библиотека для LCD#include //библиотека для LCD#include //библиотека задержкиunsigned char rom_code[16][9]; //масив с адресами найденых датчиковchar lcd_buffer[16]; //масив с данными для экранаunsigned char devices=9, iw=0; //переменная в которой количество присоеденённых датчиков, и номер выбранного датчикаint temp; //переменная для хранения температурыvoid main(void) { PORTB=0b00000010; // Port B initializationDDRB=0b00000000; // PORTC=0b11000000; // Port C initializationDDRC=0b00000000;PORTD=0b00000000; // Port D initializationDDRD=0b00000000;ACSR=0x80; // Analog Comparator: Offlcd_init(16); //инициилизация LCD, и говорим что он на 16 символовdevices=w1_search(0xf0,rom_code); //ищим датчики, и записуем их адреса в масивwhile(devices>0) //бесконечный цикл, если датчик подключон{ if (PINB.1==1 ) { //Если нажата кнопкаiw++; //Увиличиваем переменную “i” на 1delay_ms(300); //Ждём 300мс для “анти-дребезга”}if(iw>=devices){ delay_ms(5); //Если “iw” больше или равно найденым датчикамiw=0; //тогда “i” равно нулю}temp=ds18b20_temperature(&rom_code[iw][0]); //читаем температуру с выбранного датчикаif (temp>1000){ //если датчик выдаёт больше 1000temp=4096-temp; //отнимаем от данных 4096temp=-temp; //и ставим знак “минус”};if (temp > -1000) // установим порог если обрыв датчика temp= temp;else{temp =0; // выводим ноль} sprintf(lcd_buffer,”t%i=%i.%u xdfC”, iw,temp,temp%1); //записуемв масив для экрана температуру и всё такоеlcd_clear(); //чистим дисплей перед выводомlcd_puts(lcd_buffer); //выводим масив на LCDdelay_ms(50); //ждём 500мс};}

Проект такого подключения датчиков ds18b20  

Fuse бит , при прошивке МК выставить так

Источник: http://sxem.org/2-vse-stati/codevisionavr/71-codevisionavr?start=3

Классический термометр на AVR со статистикой |GrakovNe – Пробуя, создавать лучшее

20 октября 2014
Категория: Дневник AVR-щика

Всем теплых вечеров!

На самом деле, идея термометра именно в спальне у меня родилась в тот момент, когда я узнал, что существует  понятие «комфортной температуры для сна». Но просто термометр — 50 рублей на любом рынке. 100 — если электронный. И самоделка на AVR здесь никак не оправдывает себя.

Так проходили годы… ну, полгода. А потом я перевел дом на газовое отопление с контролем комнатной температуры. И мне стало интересно — «на самом ли деле эту штука позволяет держать температуру с доме постоянной и днем и ночью?».

Так и родилась идея термометра с возможностью отслеживания колебаний температуры.

Итак, задача (она же идея): Термометр должен раз в какое -то время замерять температуру, а на дисплее отображать: Текущую, Максимальную и Минимальную температуру за все время измерений. После перезагрузки все значения обнуляются.

Так, что нам нужно. Во — первых, микруха. Как обычно, моя любимица AtMega88PA-PU. Во-ворых, термодатчик (ну не из воздуха ж данные брать…Хотя, как раз именно из воздуха, хе-хе). Датчиком будет классический DS18B20. Ну, и дисплей. Возьмем простой, как грабли, WinStar WH1602 на контроллере HD44780.

Ну, разумеется, все это упакуется в какой-нибудь корпус (я честно купил. Для самоделанья корпусов руки у меня явно кривоваты) и раз уж у нас дисплей с подсветкой (мой любимый синий цвет), пусть будет клавиша, которая будет ее выключать/включать. Для удобства и из моей природной лени возьмем обычную клавишу с фиксацией и тогда для работы с подсветкой МК вообще не нужен.

Ах, да! печатной платы не будет. Корпус я взял по размеру дисплея, поэтому МК с кучей проводов просто оболью клеем. Не делайте так.

Так, все собрали и разложили. Теперь подумаем что и куда развести.

Пусть дисплей занимает целый порт B, линия данных термодатчика висит на PC0, а питание и землю он будет брать с PC1 и GND.

Тогда не придется тащить еще одну связку проводов (кстати, такая запитка очень удобна. Если нам не нужен датчик — мы всегда может его обесточить и сэкономить немного батарейки)

Если нарисовать в Proteus’е…

Получится примерно так. (питание датчика не отображено).

Ну, прицепить дисплей и датчик в корпусе TO-92 — это дело пустяковое. Теперь напишем прошивку.

Раз уж я пишу в CodeVisionAVR, то буду пользоваться встроенной либой для работы с термодатчиком. Так что вся работа сведется к двум функциям: «найти температуру и обновить статистику» и «нарисовать температуру на дисплее».

Искать будем так:

void GetTemp(){ ds18b20_init(0,0,100,DS18B20_9BIT_RES); Temp = ds18b20_temperature(0); if (Temp > MaxTemp) MaxTemp = Temp; if (Temp

А рисовать вот так:

void DrawTemp(){ GetTemp(); lcd_clear(); if (Temp == -9999) { sprintf(Buffer, “SENSOR”); lcd_gotoxy(5,0); lcd_puts(Buffer); sprintf(Buffer, “IS NOT CONNECTED”); lcd_gotoxy(0,1); lcd_puts(Buffer); } else { if ((Temp 99)) { sprintf(Buffer, “INVALID”); lcd_gotoxy(0,0); lcd_puts(Buffer); sprintf(Buffer, “TEMPERATURE”); lcd_gotoxy(5,1); lcd_puts(Buffer); MinTemp = 0; MaxTemp = 0; } else { sprintf(Buffer, “CURRENT : %+02dC”, Temp); lcd_gotoxy(1,0); lcd_puts(Buffer); sprintf(Buffer, “MAX: %02d MIN: %02d”, MaxTemp, MinTemp); lcd_gotoxy(0,1); lcd_puts(Buffer); } } }

А теперь в по срабатыванию таймера (у меня это Timer1) будем вызывать DrawTemp() и уводить МК в сон.

Надеюсь ничего непонятного не встретилось? Отлично!

Теперь — прошьем МК и начнем разводить все это «в железе»

 Соберем и распаяем элементы.

И запихаем упакуем в корпус.

Страшно? Ничего, закрываем крышку и думаем о хорошем

Вот так! 

Откуда питание? Из настольной лампы. Там уже год как болтается 5-вольтовый адаптер, от которого я иногда подзаряжал телефон.

Скачать исходники, прошивку и макет для Proteus можно здесь

P.S. А температура ночью все равно опускается на 3-4 градуса, так что газовое отопление — не такая уж идеальная вещь.

Искренне Ваш, замеряющий влажность в комнате, GrakovNe

Источник: https://old.grakovne.org/postno44/

Подключение датчика ds18b20 к микроконтроллеру ATmega8535

Источник: http://mega-avr.ucoz.ru/publ/ds18b20_connect_atmega8535/1-1-0-15

Измерение температуры на AVR. Термометр на AVR на DS18B20. Урок avr 11

Источник: http://articles.greenchip.com.ua/1-0-19.html

Ссылка на основную публикацию
Adblock
detector
",css:{backgroundColor:"#000",opacity:.6}},container:{block:void 0,tpl:"
"},wrap:void 0,body:void 0,errors:{tpl:"
",autoclose_delay:2e3,ajax_unsuccessful_load:"Error"},openEffect:{type:"fade",speed:400},closeEffect:{type:"fade",speed:400},beforeOpen:n.noop,afterOpen:n.noop,beforeClose:n.noop,afterClose:n.noop,afterLoading:n.noop,afterLoadingOnShow:n.noop,errorLoading:n.noop},o=0,p=n([]),h={isEventOut:function(a,b){var c=!0;return n(a).each(function(){n(b.target).get(0)==n(this).get(0)&&(c=!1),0==n(b.target).closest("HTML",n(this).get(0)).length&&(c=!1)}),c}},q={getParentEl:function(a){var b=n(a);return b.data("arcticmodal")?b:(b=n(a).closest(".arcticmodal-container").data("arcticmodalParentEl"),!!b&&b)},transition:function(a,b,c,d){switch(d=null==d?n.noop:d,c.type){case"fade":"show"==b?a.fadeIn(c.speed,d):a.fadeOut(c.speed,d);break;case"none":"show"==b?a.show():a.hide(),d();}},prepare_body:function(a,b){n(".arcticmodal-close",a.body).unbind("click.arcticmodal").bind("click.arcticmodal",function(){return b.arcticmodal("close"),!1})},init_el:function(d,a){var b=d.data("arcticmodal");if(!b){if(b=a,o++,b.modalID=o,b.overlay.block=n(b.overlay.tpl),b.overlay.block.css(b.overlay.css),b.container.block=n(b.container.tpl),b.body=n(".arcticmodal-container_i2",b.container.block),a.clone?b.body.html(d.clone(!0)):(d.before("
"),b.body.html(d)),q.prepare_body(b,d),b.closeOnOverlayClick&&b.overlay.block.add(b.container.block).click(function(a){h.isEventOut(n(">*",b.body),a)&&d.arcticmodal("close")}),b.container.block.data("arcticmodalParentEl",d),d.data("arcticmodal",b),p=n.merge(p,d),n.proxy(e.show,d)(),"html"==b.type)return d;if(null!=b.ajax.beforeSend){var c=b.ajax.beforeSend;delete b.ajax.beforeSend}if(null!=b.ajax.success){var f=b.ajax.success;delete b.ajax.success}if(null!=b.ajax.error){var g=b.ajax.error;delete b.ajax.error}var j=n.extend(!0,{url:b.url,beforeSend:function(){null==c?b.body.html("
"):c(b,d)},success:function(c){d.trigger("afterLoading"),b.afterLoading(b,d,c),null==f?b.body.html(c):f(b,d,c),q.prepare_body(b,d),d.trigger("afterLoadingOnShow"),b.afterLoadingOnShow(b,d,c)},error:function(){d.trigger("errorLoading"),b.errorLoading(b,d),null==g?(b.body.html(b.errors.tpl),n(".arcticmodal-error",b.body).html(b.errors.ajax_unsuccessful_load),n(".arcticmodal-close",b.body).click(function(){return d.arcticmodal("close"),!1}),b.errors.autoclose_delay&&setTimeout(function(){d.arcticmodal("close")},b.errors.autoclose_delay)):g(b,d)}},b.ajax);b.ajax_request=n.ajax(j),d.data("arcticmodal",b)}},init:function(b){if(b=n.extend(!0,{},a,b),!n.isFunction(this))return this.each(function(){q.init_el(n(this),n.extend(!0,{},b))});if(null==b)return void n.error("jquery.arcticmodal: Uncorrect parameters");if(""==b.type)return void n.error("jquery.arcticmodal: Don't set parameter \"type\"");switch(b.type){case"html":if(""==b.content)return void n.error("jquery.arcticmodal: Don't set parameter \"content\"");var e=b.content;return b.content="",q.init_el(n(e),b);case"ajax":return""==b.url?void n.error("jquery.arcticmodal: Don't set parameter \"url\""):q.init_el(n("
"),b);}}},e={show:function(){var a=q.getParentEl(this);if(!1===a)return void n.error("jquery.arcticmodal: Uncorrect call");var b=a.data("arcticmodal");if(b.overlay.block.hide(),b.container.block.hide(),n("BODY").append(b.overlay.block),n("BODY").append(b.container.block),b.beforeOpen(b,a),a.trigger("beforeOpen"),"hidden"!=b.wrap.css("overflow")){b.wrap.data("arcticmodalOverflow",b.wrap.css("overflow"));var c=b.wrap.outerWidth(!0);b.wrap.css("overflow","hidden");var d=b.wrap.outerWidth(!0);d!=c&&b.wrap.css("marginRight",d-c+"px")}return p.not(a).each(function(){var a=n(this).data("arcticmodal");a.overlay.block.hide()}),q.transition(b.overlay.block,"show",1*")),b.overlay.block.remove(),b.container.block.remove(),a.data("arcticmodal",null),n(".arcticmodal-container").length||(b.wrap.data("arcticmodalOverflow")&&b.wrap.css("overflow",b.wrap.data("arcticmodalOverflow")),b.wrap.css("marginRight",0))}),"ajax"==b.type&&b.ajax_request.abort(),p=p.not(a))})},setDefault:function(b){n.extend(!0,a,b)}};n(function(){a.wrap=n(document.all&&!document.querySelector?"html":"body")}),n(document).bind("keyup.arcticmodal",function(d){var a=p.last();if(a.length){var b=a.data("arcticmodal");b.closeOnEsc&&27===d.keyCode&&a.arcticmodal("close")}}),n.arcticmodal=n.fn.arcticmodal=function(a){return e[a]?e[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?void n.error("jquery.arcticmodal: Method "+a+" does not exist"):q.init.apply(this,arguments)}}(jQuery)}var debugMode="undefined"!=typeof debugFlatPM&&debugFlatPM,duplicateMode="undefined"!=typeof duplicateFlatPM&&duplicateFlatPM,countMode="undefined"!=typeof countFlatPM&&countFlatPM;document["wri"+"te"]=function(a){let b=document.createElement("div");jQuery(document.currentScript).after(b),flatPM_setHTML(b,a),jQuery(b).contents().unwrap()};function flatPM_sticky(c,d,e=0){function f(){if(null==a){let b=getComputedStyle(g,""),c="";for(let a=0;a=b.top-h?b.top-h{const d=c.split("=");return d[0]===a?decodeURIComponent(d[1]):b},""),c=""==b?void 0:b;return c}function flatPM_testCookie(){let a="test_56445";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function flatPM_grep(a,b,c){return jQuery.grep(a,(a,d)=>c?d==b:0==(d+1)%b)}function flatPM_random(a,b){return Math.floor(Math.random()*(b-a+1))+a}
");let k=document.querySelector(".flat_pm_modal[data-id-modal=\""+a.ID+"\"]");if(-1===d.indexOf("go"+"oglesyndication")?flatPM_setHTML(k,d):jQuery(k).html(b+d),"px"==a.how.popup.px_s)e.bind(h,()=>{e.scrollTop()>a.how.popup.after&&(e.unbind(h),f.unbind(i),j())}),void 0!==a.how.popup.close_window&&"true"==a.how.popup.close_window&&f.bind(i,()=>{e.unbind(h),f.unbind(i),j()});else{let b=setTimeout(()=>{f.unbind(i),j()},1e3*a.how.popup.after);void 0!==a.how.popup.close_window&&"true"==a.how.popup.close_window&&f.bind(i,()=>{clearTimeout(b),f.unbind(i),j()})}f.on("click",".flat_pm_modal .flat_pm_crs",()=>{jQuery.arcticmodal("close")})}if(void 0!==a.how.outgoing){let b,c="0"==a.how.outgoing.indent?"":" style=\"bottom:"+a.how.outgoing.indent+"px\"",e="true"==a.how.outgoing.cross?"":"",f=jQuery(window),g="scroll.out"+a.ID,h=void 0===flatPM_getCookie("flat_out_"+a.ID+"_mb")||"false"!=flatPM_getCookie("flat_out_"+a.ID+"_mb"),i=document.createElement("div"),j=jQuery("body"),k=()=>{void 0!==a.how.outgoing.cookie&&"false"==a.how.outgoing.cookie&&h&&(jQuery(".flat_pm_out[data-id-out=\""+a.ID+"\"]").addClass("show"),j.on("click",".flat_pm_out[data-id-out=\""+a.ID+"\"] .flat_pm_crs",function(){flatPM_setCookie("flat_out_"+a.ID+"_mb",!1)})),(void 0===a.how.outgoing.cookie||"false"!=a.how.outgoing.cookie)&&jQuery(".flat_pm_out[data-id-out=\""+a.ID+"\"]").addClass("show")};switch(a.how.outgoing.whence){case"1":b="top";break;case"2":b="bottom";break;case"3":b="left";break;case"4":b="right";}jQuery("body > *").eq(0).before("
"+e+"
");let m=document.querySelector(".flat_pm_out[data-id-out=\""+a.ID+"\"]");-1===d.indexOf("go"+"oglesyndication")?flatPM_setHTML(m,d):jQuery(m).html(e+d),"px"==a.how.outgoing.px_s?f.bind(g,()=>{f.scrollTop()>a.how.outgoing.after&&(f.unbind(g),k())}):setTimeout(()=>{k()},1e3*a.how.outgoing.after),j.on("click",".flat_pm_out .flat_pm_crs",function(){jQuery(this).parent().removeClass("show").addClass("closed")})}countMode&&(flat_count["block_"+a.ID]={},flat_count["block_"+a.ID].count=1,flat_count["block_"+a.ID].click=0,flat_count["block_"+a.ID].id=a.ID)}catch(a){console.warn(a)}}function flatPM_start(){let a=flat_pm_arr.length;if(0==a)return flat_pm_arr=[],void jQuery(".flat_pm_start, .flat_pm_end").remove();flat_body=flat_body||jQuery("body"),!flat_counter&&countMode&&(flat_counter=!0,flat_body.on("click","[data-flat-id]",function(){let a=jQuery(this),b=a.attr("data-flat-id");flat_count["block_"+b].click++}),flat_body.on("mouseenter","[data-flat-id] iframe",function(){let a=jQuery(this),b=a.closest("[data-flat-id]").attr("data-flat-id");flat_iframe=b}).on("mouseleave","[data-flat-id] iframe",function(){flat_iframe=-1}),jQuery(window).on("beforeunload",()=>{jQuery.isEmptyObject(flat_count)||jQuery.ajax({async:!1,type:"POST",url:ajaxUrlFlatPM,dataType:"json",data:{action:"flat_pm_ajax",data_me:{method:"flat_pm_block_counter",arr:flat_count}}})}).on("blur",()=>{-1!=flat_iframe&&flat_count["block_"+flat_iframe].click++})),flat_userVars.init();for(let b=0;bflat_userVars.textlen||void 0!==a.chapter_sub&&a.chapter_subflat_userVars.titlelen||void 0!==a.title_sub&&a.title_subc&&cc&&c>d&&(b=flatPM_addDays(b,-1)),b>e||cd||c-1!=flat_userVars.referer.indexOf(a))||void 0!==a.referer.referer_disabled&&-1!=a.referer.referer_disabled.findIndex(a=>-1!=flat_userVars.referer.indexOf(a)))&&(c=!0),c||void 0===a.browser||(void 0===a.browser.browser_enabled||-1!=a.browser.browser_enabled.indexOf(flat_userVars.browser))&&(void 0===a.browser.browser_disabled||-1==a.browser.browser_disabled.indexOf(flat_userVars.browser)))){if(c&&void 0!==a.browser&&void 0!==a.browser.browser_enabled&&-1!=a.browser.browser_enabled.indexOf(flat_userVars.browser)&&(c=!1),!c&&(void 0!==a.geo||void 0!==a.role)&&(""==flat_userVars.ccode||""==flat_userVars.country||""==flat_userVars.city||""==flat_userVars.role)){flat_pm_then.push(a),flatPM_setWrap(a),flat_body.hasClass("flat_pm_block_geo_role")||(flat_body.addClass("flat_pm_block_geo_role"),flatPM_ajax("flat_pm_block_geo_role")),c=!0}c||(flatPM_setWrap(a),flatPM_next(a))}}}let b=jQuery(".flatPM_sticky");b.each(function(){let a=jQuery(this),b=a.data("height")||350,c=a.data("top");a.wrap("
");let d=a.parent()[0];flatPM_sticky(this,d,c)}),debugMode||countMode||jQuery("[data-flat-id]:not([data-id-out]):not([data-id-modal])").contents().unwrap(),flat_pm_arr=[],jQuery(".flat_pm_start, .flat_pm_end").remove()}

В комплекте с CodeVisionAVR имеется библиотека ds18b20.h ( соответственно в составе с ds18b20.lib ), которая позволяет работать с датчиком температуры ds18b20 – основная задача, заключается в предоставлении значения измеренной температуры. В этой статье поговорим о некоторых, наиболее применимых функциях библиотеки.

Небольшой обзорDS18B20 – это цифровой термометр с программируемым разрешением, от 9 до 12–bit, которое может сохраняться в EEPROM памяти прибора. DS18B20 обменивается данными по 1-Wire шине и при этом может быть как единственным устройством на линии так и работать в группе. Все процессы на шине управляются центральным микропроцессором.DS18B20 состоит из ПЗУ содержащее 64-битный последовательный код, который позволяет, общаться с множеством датчиков DS18B20 установленных на одной шине, контроллера MicroLAN, температурного датчика, двух регистров для хранения верхнего и нижнего порогов температуры и регистра конфигурации. Регистр конфигурации позволяет пользователю устанавливать разрешающую способность цифрового преобразователя температуры к 9, 10, 11, или 12 битам, это и влияет на время конвертирования температуры.Термометр не содержит внутреннего источника, а использует “паразитное” питание от однопроводной шины. Однако при измерении температуры и записи данных в ЭППЗУ ток потребления микросхемы превышает 1 мА, в то время как максимальный ток, который может обеспечить ведущий шины с помощью нагрузочного резистора 1,5…5 кОм, составляет 3,3…1 мА. Применение внешнего источника питания ускоряет преобразование температуры, поскольку от ведущего шины не требуется ожидания в течение максимально возможного времени преобразования. В этом случае все приборы DS18B20, расположенные на шине, могут выполнять преобразование температуры одновременно и во время обмена данными шины MicroLAN.После завершения преобразования полученное значение сравнивается с величинами, хранящимися в регистрах TH и TL. Если измеренная температура выходит за установленные пределы, устанавливается сигнальный “флаг” (впрочем, его установка производится после каждого измерения). Выходные температурные данные DS18B20 калиброваны в градусах Цельсия.Внешний вид датчика в разных, корпусных исполнениях

Расположение выводов

 1- GND – корпус.2- DQ – линия вводавывода данных.3- Vdd – питание датчика.

Схема подключения

На один датчик
Программная часть. Подключение одного датчика

Подключим единственный датчик к микроконтроллеру atmega8535. Теперь начинаем творить программную часть. Подключаем к основному коду программы заголовочный файл ds18b20.h

#include Чтобы начать работать с одним датчиком, достаточно воспользоваться двумя функциями:

Функция инициализации

ds18b20_init( адрес датчика, нижний порог Т, верхний порог Т, разрешающая способность );

функция чтения температуры

ds18b20_temperature( адрес датчика );

Структура будущей программы

……

void main( void )

{   …  … 

  if( //инициализация ds18b20 ) //Проверяем, есть ли устройство на линии 1-wire

  {     

    while( 1 ){ //Цикл, в котором выполняется чтение и вывод значения температуры на LCD

   

    if( ) { } //Проверяем считанную температуру на отрицательное значение

   

    if( ) { } //Аварийное состояние считанной температуры

       }

  }else{ } //Ошибка – устройство не найденно 

}

Полный код программы:

//Цель: производим чтение температуры и выводим на LCD индикатор
#include
#include
#include

#include
#asm  .equ __lcd_port=0x15; PORTC#endasm
#include
#asm    .equ __w1_port=0x1B; PORTA  .equ __w1_bit=0 

#endasm

int temper;                //Переменая для хранения значения температуры

unsigned char lcdBuff[16]; //Массив для хранения фоматированной строки

#pragma rl+

char *str1=”найден датчик ds18b20″;
char *str2=”датчик ds18b20 отсутствует”;
#pragma rl-

void main( void )

{  lcd_init( 16 );  lcd_clear( );   

  if( ds18b20_init( 0, 30, 60, DS18B20_12BIT_RES ) ) //инициализация датчика. Анализ присутствия датчика

  {    lcd_clear( ); lcd_puts( str1 ); delay_ms( 1000 );     

  while( 1 ){

   

    temper=ds18b20_temperature( 0 ); //Чтение температуры, адрес нуль

    delay_ms( 30 );   

  //Анализ на отрицательную температуру

  if( temper>1000 ) { temper=4096-temper; temper=-temper; }

//если переменая temper больше 1000                                                            //То вычитаем от 4096 значение                                                            //переменой temper и далее

                                                            //присваиваем ей знак минус

if( temper>60 ) { /* какая-либо функция, например alarm ( ); */ } //Аварийное состояние считанной температуры
  sprintf( lcdBuff,”t %uxdfC”, temper ); //помещаем форматированую строку в массив
   //выводим на индикатор значение температуры  lcd_clear( ); lcd_gotoxy( 0,0 ); lcd_puts( lcdBuff ); }    

  }else{ lcd_clear( ); lcd_puts( str2 ); }  

}

Проект использования одного датчика ds18b20

Если необходимо выводить значение температуры с точностью до одной сотой, необходимо в функции sprintf заменить тип формата %u на %.3f ( как использовать этот тип формата, будет описано ниже ) и переменную temper объявить как float.


Описание программной части
Функция инициализации датчика ds18b20:

unsigned char ds18b20_init( unsigned char *addr, signed char temp_low, signed char temp_high, unsigned char resolution );

*addr            – адрес датчика ( ROM данные ), к которому обращается микроконтроллер в случае, когда их много.

                         Если датчик один, то всегда нуль.  

temp_low      – значение нижнего порога температуры

temp_high    – значение верхнего порога температуры
resolution  – установка разрешающей способности цифрового преобразователя температуры к 9, 10, 11, или 12                        битам. Принимает значения:  • DS18B20_9BIT_RES• DS18B20_10BIT_RES• DS18B20_11BIT_RES

• DS18B20_12BIT_RES

Функция возвращает положительное значение в случае присутствия датчика на линии 1-wire.Функция чтения температуры:

float ds18b20_temperature( unsigned char *addr );

*addr – адрес датчика, к которому обращается микроконтроллер в случае, когда их много. Если датчик один, то всегда нуль.

Функция возвращает число с плавающей точкой значения температуры ( тип float

Подключение двух датчиков

При подключении более одного датчика ds18b20 на линию 1-wire, необходимо выполнять чтение ROM каждого датчика, чтоб обращаться к каждому индивидуально. Используя функцию w1_search, производим поиск устройств 1-wire, тем самым выясняем их количество на линии и производим чтение ROM данных каждого датчика:

unsigned char devices;
unsigned char rom_code[2][9];

devices=w1_search( 0xF0, rom_code ); //0xF0 можно заменить на DS18B20_SEARCH_ROM_CMD

 
Переменная devices будет содержать целое число найденых устройств 1-wire ( датчики ds18b20 ), а массив rom_code будет содержать 8байт ( 64бита ) уникального кода датчика ds18b20. Этот код имеет следующий состав:Теперь по прочитанному ROM-коду можно обращаться к соответствующим датчикам.

Полный код программы

#include
#include
#include
#include
#asm  .equ __lcd_port=0x15; PORTC

#endasm

#include
#asm    .equ __w1_port=0x1B; PORTA  .equ __w1_bit=0 

#endasm 

#pragma rl+

char*str1=”ЧТЕНИЕ ТЕМПЕРАТУРЫ”;
char *str2=”No SENSOR!”;
#pragma rl-

unsigned char devices;

unsigned char LcdBuffDevices[20];
unsigned char RomCode[2][9];
unsigned char LcdBuff1[20];
unsigned char LcdBuff2[20];

void main( void )

{  lcd_init( 20 );  lcd_clear( );   

  devices=w1_search( DS18B20_SEARCH_ROM_CMD, RomCode ); //поиск датчиков на линии 1-wire

   

  if( devices )

  {

    sprintf( LcdBuffDevices,”DS18B20 = %u”, devices ); //выводим информацию о кол-ве датчиков

       lcd_gotoxy( 0,1 ); lcd_puts( LcdBuffDevices ); lcd_gotoxy( 0,0 ); lcd_puts( str1 );   

    ds18b20_init( &RomCode[0][0], 30, 60, DS18B20_12BIT_RES ); //инициализация первого датчика

    ds18b20_init( &RomCode[1][0], 30, 60, DS18B20_12BIT_RES ); //инициализация второго датчика

  while( 1 )

  {

    //чтение температуры первого датчика

    sprintf( LcdBuff1,”t1 %.2f xefC”, ds18b20_temperature( &RomCode[0][0] ) );
     lcd_gotoxy( 0,2 ); lcd_puts( LcdBuff1 );   

    //чтение температуры второго датчика

    sprintf( LcdBuff2,”t2 %.2f xefC”, ds18b20_temperature( &RomCode[1][0] ) );Впрочем инициализацию можно не выполнять, в том случае, если от датчика не требуется чтение «аварии», тем более по умолчанию установлено 12 битное значение преобразования температуры. 

Вспомним функцию sprintf ( Функция sprintf стандартной библиотеки stdio.h ).Используем тип формата f – число с плавающей точкой в записи с фиксированной десятичной точкой, т.е:

%.0f – без вывода после запятой   t 20 'C
%.1f – единицы                            t 20.6 'C
%.2f – десятки                            t 20.62 'C
%.3f – сотки                               t 20.625 'C

Чтобы данный тип формата работал в функции, необходимо в среде CodeVisionAVR зайти в Configure the project выбрать вкладку C Compiler, Code Generation выбрать из списка (s)printf Features строку float, width, precision 

Цикл программы, в котором происходит чтение температуры датчиковwhile( 1 )  {

    //чтение температуры первого датчика

    sprintf( LcdBuff1,”t1 %.2f xefC”, ds18b20_temperature( &RomCode[0][0] ) );    lcd_gotoxy( 0,2 ); lcd_puts( LcdBuff1 );   

    //чтение температуры второго датчика

    sprintf( LcdBuff2,”t2 %.2f xefC”, ds18b20_temperature( &RomCode[1][0] ) );    lcd_gotoxy( 0,3 ); lcd_puts( LcdBuff2 );

  }

Можно изменить на такой, более удобный

unsigned char num=1;

while( 1 )  {

    //чтение температуры датчиков (  испытание на два датчика )

    do{ sprintf( LcdBuff1,”t%u %.2f xefC”,num, ds18b20_temperature( &RomCode[j][0] ) );        lcd_gotoxy( 0,j );    lcd_puts( lcdBuff );   

    if(

num

Опубликовано 2010-09-20 15:21:28 автором Ruslan

В устройствах автоматики очень часто нужно контролировать какой-либо параметр окружающей среды: температуру, влажность, освещенность, давление и т.д. Для этого существуют датчики – устройства, которые преобразуют одну физическую величину в другую.

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

Сегодня я покажу, как цифровой датчик температуры DS18B20 подружится с микроконтроллером avr atmega8.

  1. GND – минус питания.
  2. DQ – линия вводавывода данных.
  3. Vdd – плюс питания.

Датчик температуры DS18B20 – микросхема с тремя выводами, DS18B20 обменивается данными по шине 1-Wire. На одной шине может быть оооочень много датчиков, это достигается за счет того, что каждый DS18B20 имеет свой уникальный код, и микроконтроллер таким образом инициализирует передачу данных с определенным датчиком на шине.
Диапазон измеряемых температур от –55°C до +125°C и точностью 0.5°C. Разрешающая способность по умолчанию установлена 12-бит, но может быть изменена пользователем на 9, 10, или 11 бит. Еще одна особенность DS18B20 – это возможность работать без внешнего питания, он может питаться от линии данных (“parasite power”), при отсутствии внешнего источника. Эта способность реализуется за счет того что внутри датчика есть конденсатор, который заряжается через подтягивающий резистор от высокого уровня на линии данных. Этот метод часто называют «Паразитным питанием».
Давайте соберем простой термометр на DS18B20 и микроконтроллере atmega8. Цифровой термометр должен измерять температуру и выводить ее на lcd дисплей. Схема термометра выглядит следующим образомВ CodeVision есть специальная библиотека для работы с DS18B20. В ней находятся все необходимые функции для работы с ним. Для того, чтобы использовать данный датчик в своих конструкциях, необходимо выполнить ряд несложных процедур по подключению датчика. На физическом уровне датчик подключается к одному из выводов любого порта. Вывод GND соединяется с общим проводом, вывод Vdd подключается к +5 В, а вывод DQ к линии выбранного порта. При этом на вывод DQ относится подтягивающий резистор (обычно 4,7 к), второй вывод которого подключается к +5 В. Программа выглядит так
#include
#include // 1 Wire Bus functions //указываем, куда подключен датчик #asm .equ __w1_port=0x18 ;PORTB .equ __w1_bit=0 #endasm #include //библиотека для работы с датчиком ds18b20 // Alphanumeric LCD Module functions //указываем, куда подключён экран #asm .equ __lcd_port=0x12 ;PORTD #endasm #include //библиотека для LCD #include // библиотека, в которой живет функция sprintf char lcd_buf[16]; // масив, в котором формируются данные для вывода на lcd float temperature; // переменная, в которой будет храниться значение температуры void main(void) { lcd_init(16); // инициализация LCD на 16 символов w1_init(); // // инициализация шины 1 wire while(1) { temperature = ds18b20_temperature(0); //получаем температуру от датчика 0 sprintf(lcd_buf,”t=%.1fxdfC”,temperature); // формируем строку для вывода lcd_clear(); // чистим дисплей lcd_puts(lcd_buf); // выводим содержимое массива lcd_buf на дисплей delay_ms(1000); // делаем задержку в 1 секунду }; }

По программе вроде все понятно, единственное только – надо в свойствах проекта указать (s)printf features float и частоту мк выставить на 1 mhz, для этого переходим Project->Configure-> C Compiler и выставляем все как на скриншотеКомпилируем и получаем термометрКак видите, подключить датчик температуры к мк не составляет никакого труда, 20 минут и термометр на lcd готов.

Сейчас мы сделаем еще один термометр но с выводом температуры на Led (семисегментный индикатор). C термометром на семисегментнике не все так просто, как кажется на первый взгляд. Дело в том что функция ds18b20_temperature блокирует выполнение основного потока, пока датчик не пришлет значение температуры, а это около одной секунды. Вот исходный код функции
float ds18b20_temperature(unsigned char *addr) { unsigned char resolution; if (ds18b20_read_spd(addr)==0) return -9999; resolution=(__ds18b20_scratch_pad.conf_register>>5) & 3; if (ds18b20_select(addr)==0) return -9999; w1_write(0x44); delay_ms(conv_delay[resolution]); вот на этом delay_ms главный поток и останавливается if (ds18b20_read_spd(addr)==0) return -9999; w1_init(); return (*((int *) &__ds18b20_scratch_pad.temp_lsb) & ((int) bit_mask[resolution]))*0.0625; }

а у нас-то индикация на семисегментнике динамическая, это значит что семисегментник будет зависать на период измерения температуры. Чтобы решить эту проблему, нам придется вручную посылать команды DS18B20.

Алгоритм такой: послали команду на измерение температуры, и дальше занимаемся своими делами

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

Вывод значения температуры на дисплей состоит из следующих шагов:

  1. Определяем знак температуры и отражаем его на дисплее
  2. Если температура отрицательная, превратим ее в положительную.
  3. Выделяем с помощью битовых масок целую часть температуры, переводим в символы и отражаем на дисплее.

    Чтобы перевести оцифрованное значение температуры в градусы, нужно это значение умножить на вес младшего разряда. Для целой части температуры вес младшего разряда (BIT4) равен 1 градусу Целься, а значит умножать ничего не нужно.

  4. Выделяем дробную часть, преобразуем дробную часть в целую, переводим в символы и отражаем на дисплее.