Технический форум по робототехнике.
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);
};
};
}
foxit » 08 июл 2008, 16:56
В примерах к компилятору есть программа для работы с данным датчиком
Проверял работает
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);
};
};
}
Скомпилировал и засунул в Протеус и получил
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".
snayperAlfa » 08 июл 2008, 21:08
ОГРОМНЕЙШЕЕ ТЕБЕ СПАСИБО.Таки заработало.Буду теперь знать про такую ехидную опцию
Добавлено спустя 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);
};
};
Но все равно медленно
snayperAlfa » 09 июл 2008, 23:07
Может ктото знает как ускорить индикацию температуры.Ибо сильно мееедленннннно меняются показания.
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мс стирание всего на дисплее каждый раз введя проверку на изменение измеряемой тем-ры - то есть если оная изменилась - очистим, нет - не будем, таким образом можно все же немного, но сэкономить.