Продолжаем осваивать периферию, на очереди измерение температуры. Рассмотрим вариант измерения, при помощи датчика температуры DS18b20.
Характеристики датчика: диапазон измерения от -55 до +125°С. Точность измерения ±0,5°С гарантируется в диапазоне от -10 до +85°С. Возможность измерения с разрешением 9, 10, 11 и 12 бит, т.е. с шагом 0,5; 0,25; 0,125; 0,0625°С. Для обмена информацией с AVR микроконтроллером используется 1-Wire протокол. Каждый датчик имеет свой уникальный адрес, поэтому имеется возможность посадить на шину сразу несколько датчиков.
Для сборки схемы понадобится жк дисплей, датчик и резистор на 4,7кОм. Теперь перейдем непосредственно к прошивке.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #include <mega8.h> #include <delay.h> // 1 Wire Bus functions #asm .equ __w1_port=0x18 ;PORTB .equ __w1_bit=2 #endasm #include <1wire.h> #include <ds18b20.h> // Alphanumeric LCD Module functions #asm .equ __lcd_port=0x12 ;PORTD #endasm #include <lcd.h> #include <stdio.h> char lcd_buf[17]; void main(void) { float temper; lcd_init(16); w1_init(); ds18b20_init(0,-20,50,DS18B20_12BIT_RES); while(1) { temper=ds18b20_temperature(0); sprintf(lcd_buf,"t=%.1f\xdfC",temper); lcd_clear(); lcd_puts(lcd_buf); delay_ms(1500); }; } |
Теперь обо всем по порядку:
1 2 3 4 | #asm .equ __w1_port=0x18 ;PORTB .equ __w1_bit=2 #endasm |
Данный код означает, что датчик подключен к порту В, PB2 ножке
1 2 | #include <1wire.h> #include <ds18b20.h> |
Используется протокол 1wire, тип датчика ds18b20
1 2 3 | float temper; w1_init(); ds18b20_init(0,-20,50,DS18B20_12BIT_RES); |
Переменная temper (с плавающей точкой) используется для хранения температуры,
w1_init(); — ищем датчик,
ds18b20_init(0,-20,50,DS18B20_12BIT_RES); — настройка датчика: 0-номер датчика, -20 -нижний предел измерения, 50 — верхний предел измерения,
DS18B20_12BIT_RES используется 12 битный режим(с шагом 0,0625°С). В принципе настройку можно не производить, по умолчанию выставлен 12 битный режим. Показано лишь для того, чтобы вы могли самостоятельно изменить режим измерения, если это понадобится.
1 2 3 4 5 6 | temper=ds18b20_temperature(0); sprintf(lcd_buf,"t=%.1f\xdfC",temper); lcd_clear(); lcd_puts(lcd_buf); delay_ms(1500); |
temper=ds18b20_temperature(0); — читаем значение температуры с датчика
sprintf(lcd_buf,»t=%.1f\xdfC»,temper); преобразовываем к понятному для lcd виду %.1f — вывод числа с плавающей точкой 1 знак после запятой, не забываем в свойствах проекта указать (s)printf features float.
\xdf — вывод на экран значка градуса.
В результате должно получиться нечто похожее
Отрицательной температуры поблизости не было :D, поэтому попробовал остудить бутылочкой соуса из холодильника, результат что то не сильно впечатлил.
Зато от нагрева рукой, температура довольно быстро повысилась.
Проект доступен тут
Проект для DS18s20
Проект для двух датчиков
Проект для DS18b20 на семисегментниках
Проект Алексея(Alyes)для Atmega16 и шести сегментов + бонус видео устройства
Здравствуйте! На семисигментниках собрал термометр с отображением до десятых долей градуса.В протеусе все ОК.В железе при вкл на индикаторе отображается ересь-как будто два итображения чисел вместе накладываются Железо вроде ОК ( с программой на два знака(целые значения температуры) все норм работает!Программу тоже пошагово проверял все нормально. Может кто подскажет в чем дело-писал пропеты и посложнее и все получалось , а тут споткнулся…
это нормально 🙂 попробуйте реже опрашивать для начала.
Здравствуйте Уважаемый Admin! Подскажите пожалуйста как в Codevisionavr 2.05 сделать проект с двумя и более температурными датчиками DS18B20? В конце Вашей статьи есть Проект Алексея(Alyes), выполненный в CVAVR 2.05, но заставить работать его с двумя датчиками никак не могу добиться. Подскажите пожалуйста куда какие стоки нужно добавить?
Спасибо.
/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.0 Professional
Automatic Program Generator
© Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
#include
#include
// 1 Wire Bus interface functions
#include
// DS1820 Temperature Sensor functions
#include
void main(void)
{
// Declare your local variables here
float temper;
unsigned int x;
// 1 Wire Bus initialization
// 1 Wire Data port: PORTD
// 1 Wire Data bit: 7
// Note: 1 Wire port settings must be specified in the
// Project|Configure|C Compiler|Libraries|1 Wire IDE menu.
w1_init();
ds18b20_init(0,-20,50,DS18B20_12BIT_RES);
// Global enable interrupts
#asm(«sei»)
while (1)
{
temper=ds18b20_temperature(0);
if (temper>1000)
{
temper=4096.0-temper;
minus=1;
}
x=temper*10;
nom4=x%10;//разборка целого числа на отдельный сегмент…
x=x/10;
nom3=x%10;
nom2=x/10;
nom5=10;
nom6=11;
if(minus==0)
{
nom1=12;
}
else
{
nom1=13;
}
}
}
посмотрите про статическую и динамическую индикацию, тут легкого пути нет.
#include
#include
// 1 Wire Bus functions
#asm
.equ __w1_port=0x18 ;PORTB
.equ __w1_bit=0
#endasm
#include
//#include
#define MAX_devices 8
unsigned char rom_code[MAX_devices][9];
// Declare your global variables here
unsigned char a,b,c;
eeprom unsigned char key[5][3]={ {0x00,0x00,0x00},
{0x00,0x00,0x00},
{0x00,0x00,0x00},
{0x00,0x00,0x00},
{0x00,0x00,0x00}};
eeprom int count_keys=0; // список ключей
int i,j,devices;
bit security=0; // 1-режим охраны, 0-снято с охраны;
//eeprom int address[4][6];
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
if (security==1)
{
PORTC.2=1;
PORTC.4=0;
}
}
// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
if (security==1)
{
PORTC.2=1;
PORTC.4=0;
}
}
void programming(void) // программирование ключей
{
if (count_keys==4) count_keys=0;
devices=w1_search(0xf0,&rom_code[0,0]);
if (devices!=0)
{
for (j=1;j<=10;j++)
{
key[count_keys][0]=rom_code[0,3];
key[count_keys][1]=rom_code[0,2];
key[count_keys][2]=rom_code[0,1];
}
count_keys=count_keys+1;
delay_ms(1000);
for (j=1;j<=count_keys;j++)
{
PORTC.5=0;
delay_ms(700);
PORTC.5=1;
delay_ms(700);
}
PORTC.5=0;
delay_ms(1000);
}
}
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;
// Port C initialization
// Func6=In Func5=Out Func4=Out Func3=In Func2=Out Func1=In Func0=In
// State6=T State5=0 State4=0 State3=T State2=0 State1=T State0=P
PORTC=0x01;
DDRC=0x34;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Low level
// INT1: On
// INT1 Mode: Low level
GICR|=0xC0;
MCUCR=0x00;
GIFR=0xC0;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// Determine the number of DS1820 devices
// connected to the 1 Wire bus
// Global enable interrupts
#asm("sei")
PORTC.4=1; // Инвертированный выход реле
while (1)
{
if (PINC.0==1) // если не включен режим программирования
{
programming(); // функция программирования ключей
for (j=1;j<=10;j++)
{
PORTC.5=!PORTC.5;
delay_ms(50);
}
}
else
{
devices=w1_search(0xf0,&rom_code[0,0]);
if (devices!=0)
{
for (j=1;j<=6;j++)
{
a=rom_code[0,3];
b=rom_code[0,2];
c=rom_code[0,1];
}
for (i=1;i<=count_keys;i++)
{
if ((key[i-1][0]==a)&(key[i-1][1]==b)&(key[i-1][2]==c))
{
PORTC.5=!PORTC.5;
security=!security;
PORTC.2=0; /// Выход сигналиции на звук
PORTC.4=1; /// Выход сигналиции на свет
}
} // for (i=1;i<=count_keys;i++)
}; //if (devices!=0)
delay_ms(300);
}; //else
} // while
}
выдает следующие ошибки:
Error: D:\Архив\уроки codevision avr\разное иредкое\ibutton\CVA\1-wire.c(56): missing ']'
Error: D:\Архив\уроки codevision avr\разное иредкое\ibutton\CVA\1-wire.c(62): missing ']'
Error: D:\Архив\уроки codevision avr\разное иредкое\ibutton\CVA\1-wire.c(187): missing ']'
Error: D:\Архив\уроки codevision avr\разное иредкое\ibutton\CVA\1-wire.c(193): missing ']'
Уважаемый помоги!!! в чем тут дело?
Спасибо!!! Разобрался 😛 😛 😛 😛
Я понял ошибку ! 🙂
Здравствуйте. Подскажите пожалуйста, возможно ли одновременное использование датчиков ds18b20 и dht11? Если да, то их нужно садить на разные порты или на один?
Заранее благодарен.
насколько я помню у них разные тайминги, поэтому подозреваю, что будут конфликтовать.
Уважаймый админ подскажите пожалуйста как можно организовать передачу данных между двумя микроконтроллерами по 1-ware. Если есть возможность пример кода, очень нужно понять. За ранее спасибо.
Очень нужна помощь
Вы можете подчерпнуть идею в статье
http://avr-start.ru/?p=2230
В кратце — организуйте простейший протокол. То как передаются данные по 1wire можно подчерпнуть
http://avr-start.ru/?p=5060
Лично на мой взгляд 1wire это самый убогий протокол, какой только можно представить.
Если точнее мне нужно подключить ds2438, чтобы мерить ток. У меня есть программа на ардуино и мне её нужно переделать под cvavr и расписать комментарии. Что это будет стоить ?
Здравствуйте! А есть проект в sprint? буду очень благодарен 😀
Друг! Помоги подключить чип ds2438 всю голову сломал. Нет библиотеки в codevisionavr нет компонента в протеусе. Нужно научиться считывать расход заряда и разряда баттареи, пожалуйста помоги. 🙁
Дмитрий, тема зарядников мне не особо интересна, по крайней мере в текущий момент. В моем понимании микросхема выдает всего лишь значения счетчиков, которые еще нужно правильно посчитать учитывая конкретную батарею, конкретную схему зарядки, температуру и прочие факторы. Учитывая это гораздо проще купить готовый зарядник и доработать под свои нужды.
Если нет библиотеки в codevisionavr как мне её опросить ? Пример кода нужен. Не понимаю как оплачивать. С ds18b20 все понятно, а с ds2438 не вьежаю.
Подскажите как вывести температуру с вещественным числом в Microchip studio7?Принцып действия.
Проекты под LCD мёртвые и данная программа в CodeVision компилируется, но не рабочая, протеус ерунду выдаёт.
Вот рабочая, только не могу разобраться, как десятые градуса вывести. В протеусе поставить 8 мГц и деление 1024. Может кто подскажет, как десятые выести?
/*******************************************************
CodeWizardAVR V2.05 Advanced
Chip type : ATmega8
Program type : Application
AVR Core Clock frequency: 8,000000 MHz
*******************************************************/
#include
#asm
.equ __w1_port=0x18 ;PORTB
.equ __w1_bit=2 // PORTB.2 к которому подсоединён датчик DS18B20.
#endasm
#include
#include
#define MAX_DS18b20 8
unsigned char rom_codes[MAX_DS18b20][9];
#include
char lcd_buffer[33];
#include
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include
int temp[8];
void main(void)
{
unsigned char i;
lcd_init(16);
delay_ms(500);
w1_search(0xf0,rom_codes);
while (1)
{
temp[0]=ds18b20_temperature(&rom_codes[i][0]);
if (temp>1000){
temp[0]=4096.0-temp[0];
temp[0]=-temp[0];
}
// пример управления при заданных температурах
if(temp[0]==10){break;} // если температура достигнет +10, остановить программу
if(temp[0]==-10){break;} // если температура достигнет -10, остановить программу
// вывод на LCD
sprintf(lcd_buffer,»t=%i.%d\xdfC»,temp[0],temp[0]%1);
lcd_clear();
lcd_puts(lcd_buffer);
delay_ms(1000);
};
lcd_clear(); //очистить экран после достижения заданной температуры
}