roboforum.ru

Технический форум по робототехнике.

Термометр:Мега16 и DS18B20

Термометр:Мега16 и DS18B20

snayperAlfa » 07 июл 2008, 21:05

Собрал термометр.Между Vdd и DQ датчика повесил резистор 5кОм.Делал по примеру в Кодевижене.МК определяет датчик,показывает его ROM код,а вместо температуры пишет следующее: t1=3f*C
Код: Выделить всёРазвернуть
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.9 Standard
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 07.07.2008
Author  : F4CG                           
Company : F4CG                           
Comments:


Chip type           : ATmega16
Program type        : Application
Clock frequency     : 11,059200 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*****************************************************/

#include <mega16.h>
#include <stdlib.h>
#include <ctype.h>
#include <delay.h>
#include <string.h>
#include <stdio.h>



// 1 Wire Bus functions
#asm
   .equ __w1_port=0x18 ;PORTB
   .equ __w1_bit=0
#endasm
#include <1wire.h>

// DS1820 Temperature Sensor functions
#include <ds18b20.h>

// Alphanumeric LCD Module functions
#asm
   .equ __lcd_port=0x1B ;PORTA
#endasm
#include <lcd.h>



// Declare your global variables here


char lcd_buffer[33];

/* maximum number of DS18B20 connected to the 1 Wire bus */
#define MAX_DEVICES 8

/* DS18B20 devices ROM code storage area */
unsigned char rom_code[MAX_DEVICES][9];
main()
{
unsigned char i,j,devices;

lcd_init(16);
lcd_putsf("CodeVisionAVR\n1 Wire Bus Demo");
delay_ms(2000);
lcd_clear();

/* detect how many DS18B20 devices
   are connected to the 1 Wire bus */
devices=w1_search(0xf0,rom_code);
sprintf(lcd_buffer,"%u DS18B20\nDevice detected",devices);
lcd_puts(lcd_buffer);
delay_ms(2000);

/* display the ROM codes for each device */
if (devices)
   {
   for (i=0;i<devices;i++)
       {
       sprintf(lcd_buffer,"Device #%u ROM\nCode is:",i+1);
       lcd_clear();
       lcd_puts(lcd_buffer);
       delay_ms(2000);
       lcd_clear();
       for (j=0;j<8;j++)
           {
           sprintf(lcd_buffer,"%02X ",rom_code[i][j]);
           lcd_puts(lcd_buffer);
           if (j==3) lcd_gotoxy(0,1);
           };
       delay_ms(5000);
       };
   }
else
while (1); /* stop here if no devices were found */

/* configure each DS18B20 device for 12 bit temperature
   measurement resolution */
for (i=0;i<devices;)
    if (!ds18b20_init(&rom_code[i++][0],20,30,DS18B20_12BIT_RES))
       {
       sprintf(lcd_buffer,"Init error for\ndevice #%u",i);
       lcd_clear();
       lcd_puts(lcd_buffer);
       while (1); /* stop here if init error */
       };

/* measure and display the temperature(s) */       
while (1)
      {
      j=1;
      for (i=0;i<devices;i++)
          {
          sprintf(lcd_buffer,"t%u=%+.3f\xdfC",j++,ds18b20_temperature(&rom_code[i][0]));
          lcd_clear();
          lcd_puts(lcd_buffer);
          delay_ms(500);
          };
      };
}

Re: Термометр:Мега16 и DS18B20

foxit » 08 июл 2008, 16:56

В примерах к компилятору есть программа для работы с данным датчиком
Проверял работает

Re: Термометр:Мега16 и DS18B20

snayperAlfa » 08 июл 2008, 17:03

Взял я данный файл из примера

Код: Выделить всёРазвернуть
/* Multipoint thermometer with LCD display
   using the Maxim DS18B20
   1 Wire bus temperature sensors

   CodeVisionAVR C Compiler
   (C) 2000-2005 HP InfoTech S.R.L.
   www.hpinfotech.ro

   Chip: ATmega8515
   Memory Model: SMALL
   Data Stack Size: 128 bytes
   
   PLEASE MAKE SURE THAT THE CKSEL0..3 FUSE
   BITS ARE PROGRAMMED TO USE THE EXTERNAL
   3.6864MHz CLOCK SOURCE OF THE STK500 AND NOT
   THE INTERNAL 1MHz OSCILLATOR.
   The ATmega8515 chip comes from the factory
   with CKSEL0..3 fuse bits set to use the
   internal 1 MHz oscillator.

   The DS18B20 sensors are connected to
   bit 6 of PORTA of the ATmega8515 as follows:

   [DS18B20]     [STK500 PORTA HEADER]
    1 GND         -   9  GND
    2 DQ          -   7  PA6
    3 VDD         -  10 +5V

   All the temperature sensors must be connected
   in parallel
   
   AN 4.7k PULLUP RESISTOR MUST BE CONNECTED
   BETWEEN DQ (PA6) AND +5V !
*/
#asm
    .equ __w1_port=0x1b
    .equ __w1_bit=6
#endasm

/* Use an 2x16 alphanumeric LCD connected
   to PORTC as follows:

  [LCD]   [STK500 PORTC HEADER]
   1 GND- 9  GND
   2 +5V- 10 VCC 
   3 VLC- LCD contrast control voltage 0..1V
   4 RS - 1  PC0
   5 RD - 2  PC1
   6 EN - 3  PC2
  11 D4 - 5  PC4
  12 D5 - 6  PC5
  13 D6 - 7  PC6
  14 D7 - 8  PC7
*/

#asm
    .equ __lcd_port=0x15
#endasm

#include <lcd.h> // LCD driver routines
#include <ds18b20.h>
#include <delay.h>
#include <stdio.h>

char lcd_buffer[33];

/* maximum number of DS18B20 connected to the 1 Wire bus */
#define MAX_DEVICES 8

/* DS18B20 devices ROM code storage area */
unsigned char rom_code[MAX_DEVICES][9];

main()
{
unsigned char i,j,devices;

lcd_init(16);
lcd_putsf("CodeVisionAVR\n1 Wire Bus Demo");
delay_ms(2000);
lcd_clear();

/* detect how many DS18B20 devices
   are connected to the 1 Wire bus */
devices=w1_search(0xf0,rom_code);
sprintf(lcd_buffer,"%u DS18B20\nDevice detected",devices);
lcd_puts(lcd_buffer);
delay_ms(2000);

/* display the ROM codes for each device */
if (devices)
   {
   for (i=0;i<devices;i++)
       {
       sprintf(lcd_buffer,"Device #%u ROM\nCode is:",i+1);
       lcd_clear();
       lcd_puts(lcd_buffer);
       delay_ms(2000);
       lcd_clear();
       for (j=0;j<8;j++)
           {
           sprintf(lcd_buffer,"%02X ",rom_code[i][j]);
           lcd_puts(lcd_buffer);
           if (j==3) lcd_gotoxy(0,1);
           };
       delay_ms(5000);
       };
   }
else
while (1); /* stop here if no devices were found */

/* configure each DS18B20 device for 12 bit temperature
   measurement resolution */
for (i=0;i<devices;)
    if (!ds18b20_init(&rom_code[i++][0],20,30,DS18B20_12BIT_RES))
       {
       sprintf(lcd_buffer,"Init error for\ndevice #%u",i);
       lcd_clear();
       lcd_puts(lcd_buffer);
       while (1); /* stop here if init error */
       };

/* measure and display the temperature(s) */       
while (1)
      {
      j=1;
      for (i=0;i<devices;i++)
          {
          sprintf(lcd_buffer,"t%u=%+.3f\xdfC",j++,ds18b20_temperature(&rom_code[i][0]));
          lcd_clear();
          lcd_puts(lcd_buffer);
          delay_ms(500);
          };
      };
}

Скомпилировал и засунул в Протеус и получил
.JPG

Re: Термометр:Мега16 и DS18B20

Co$s » 08 июл 2008, 18:04

snayperAlfa
Как вы уже наверное знаете функции print(f)/scan(f) отнимают довольно серьезное количество памяти, поэтому их обычно либо разделяют, создавая версии для типов чисел которые предполагается выводить, либо как это сделано в CVAVR - такая опция выбирается в настройках компилятора. А именно Options->C Compiler->sprintf(f) Features. Раз у вас выводится хоть какой-то результат вы эту опцию уже по всей видимости изменяли и она стоит в положении "long, width". Проблематика же в вашем случае состоит в том, что при выводе температуры, в экземпляре примера предоставляемого библиотекой CodeVisionAVR используются числа с плавающей точкой (float, что собственно из-за своих размеров весьма спорно для этого класса контроллеров, впрочем для примера вполне сойдет), а именно параметр %f (если быть точным %+.3f - то есть будет выведено три цифры после запятой) передаваемый в sprintf(). Естественно, буфер который будет применятся в этой функции при параметрах "long, width", а именно long int, ни в коем случае не сможет корректно принять числа с типом float. В итоге на вывод пойдет совсем не то что хотелось бы... Выход прост – просто выберите значение (которое кстати и стоит в этом проекте по-умолчанию) "float, width, precision".

Re: Термометр:Мега16 и DS18B20

snayperAlfa » 08 июл 2008, 21:08

ОГРОМНЕЙШЕЕ ТЕБЕ СПАСИБО.Таки заработало.Буду теперь знать про такую ехидную опцию :Bravo:

Добавлено спустя 2 часа 47 минут 7 секунд:
Как бы ускорить индикацию температуры? Я сделал след:
Код: Выделить всёРазвернуть
while (1)
      {
      int a;
      j=1;
      for (i=0;i<devices;i++)
          {
         // sprintf(lcd_buffer,"t%u=%+.3f\xdfC",j++,ds18b20_temperature(&rom_code[i][0]));
         a=ds18b20_temperature(&rom_code[i][0]);
         
          itoa(a,lcd_buffer);
          //sprintf(lcd_buffer,"t=%d",a);
          lcd_clear();
          lcd_puts(lcd_buffer);
          delay_ms(10);
         
          };
      };

Но все равно медленно

Re: Термометр:Мега16 и DS18B20

snayperAlfa » 09 июл 2008, 23:07

Может ктото знает как ускорить индикацию температуры.Ибо сильно мееедленннннно меняются показания.

Re: Термометр:Мега16 и DS18B20

Co$s » 30 июл 2008, 00:42

Для разрешения этого вопроса я бы сначала порекомендовал бы вам скачать даташит на DS18B20, там вы можете обнаружить прямую зависимость от используемого датчиком разрешения и временем преобразования. К примеру для 12 бит это ~750мс что как вы понимаете немало... Выход - уменьшить разрешение, используя стандартуную библиотеку
CVAVR, это можно сделать в функции начальной настройки датчика - ds18b20_init(&rom_code[i++][0],20,30,DS18B20_12BIT_RES), Определение DS18B20_12BIT_RES как раз и отвечает за это, я не знаю точного строения функции по считыванию темп-ры в библиотеке CVAVR, но полагаю этот параметр там учитывается и при следующих циклах чтения оной ждать придется гораздо меньше... Ну и по-мелочи... Можно убрать задержку в 500мс стирание всего на дисплее каждый раз введя проверку на изменение измеряемой тем-ры - то есть если оная изменилась - очистим, нет - не будем, таким образом можно все же немного, но сэкономить.


Rambler\'s Top100 Mail.ru counter