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

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


В устройствах автоматики очень часто нужно контролировать какой-либо параметр окружающей среды: температуру, влажность, освещенность, давление и т.д. Для этого существуют датчики - устройства, которые преобразуют одну физическую величину в другую. Для измерения температуры существует очень много разнообразных датчиков, от простейших контактных (биметаллические, ртутные) до сложных преобразователей температуры в напряжение, частоту, ток и т.д.
Сегодня я покажу, как цифровой датчик температуры DS18B20 подружится с микроконтроллером avr atmega8.

Датчик температури DS18B20 к avr

  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 дисплей.
Схема термометра выглядит следующим образом
Схема термометра на DS18B20

В CodeVision есть специальная библиотека для работы с DS18B20. В ней находятся все необходимые функции для работы с ним. Для того, чтобы использовать данный датчик в своих конструкциях, необходимо выполнить ряд несложных процедур по подключению датчика. На физическом уровне датчик подключается к одному из выводов любого порта. Вывод GND соединяется с общим проводом, вывод Vdd подключается к +5 В, а вывод DQ к линии выбранного порта. При этом на вывод DQ относится подтягивающий резистор (обычно 4,7 к), второй вывод которого подключается к +5 В.
Программа выглядит так

#include <mega8.h>
#include <delay.h> 
// 1 Wire Bus functions 
//указываем, куда подключен датчик  
#asm 
   .equ __w1_port=0x18 ;PORTB 
   .equ __w1_bit=0 
#endasm 
 
#include <ds18b20.h> //библиотека для работы с датчиком ds18b20 
  
// Alphanumeric LCD Module functions 
//указываем, куда подключён экран     
#asm 
   .equ __lcd_port=0x12 ;PORTD 
#endasm 
 
#include <lcd.h> //библиотека для LCD 
#include <stdio.h> // библиотека, в которой живет функция 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=%.1f\xdfC",temperature);   // формируем строку для вывода  
          lcd_clear();   // чистим дисплей              
          lcd_puts(lcd_buf);   // выводим содержимое массива  lcd_buf на дисплей     
          delay_ms(1000);  // делаем задержку в 1 секунду             
      };  
} 


По программе вроде все понятно, единственное только - надо в свойствах проекта указать (s)printf features float и частоту мк выставить на 1 mhz, для этого переходим Project->Configure-> C Compiler и выставляем все как на скриншоте настройка DS18B20 Компилируем и получаем термометр Термометр на DS18B20 Как видите, подключить датчик температуры к мк не составляет никакого труда, 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. Выделяем дробную часть, преобразуем дробную часть в целую, переводим в символы и отражаем на дисплее.

Комментарии - (4)

  • Sanyo.95 говорит:
    Большое спасибо автору за урок, все отлично, но кода для вывода на семисегментник нет, очень хотелось бы взглянуть.
  • Артём говорит:
    День добрый! Можете вот это: "послали команду на измерение температуры, и дальше занимаемся своими делами через полторы секунды спросили у датчика, измерил ли он температуру, если да, то получаем данные и выводим их на семисегментник. Посылать команды датчику мы будем с помощью функции w1_write. Давайте приступим к написанию кода" написать кодом, сам не допираю как всё это будет выглядеть, заранее спасибо!
  • Артём говорит:
    на странице кода не видно/нет...

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

Для отправки комментария вы должны авторизоваться.