Продолжаем осваивать периферию, на очереди измерение температуры. Рассмотрим вариант измерения, при помощи датчика температуры 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 и шести сегментов + бонус видео устройства
Видимо плохо читали, ответ на Ваш вопрос там есть.
upd: добавил еще один пример
И с кодировками понятно. Значение с ds18b20 двухбайтное. Очевидно, не понимаю, где там значение до запятой, а где после.
Все же элементарно, если умножить дробное число на 10, то дробная часть перестает быть дробной.
Подскажите, в данном коде, если использую Мегу 16 не работают указатели строки. на дисплей выводится пустота. Этот же код на Мега 8 — все работает… Причем делаю пустой проект для Мега 16, что бы просто вывести строку, не работает. С prinf и lcd_putsf проблем не возникает. Заранее спасибо.
char * _str_1="Digital"; //Создаем информ. строку
char * _str_2 ="Thermo";
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_1); // Выводим строку _str на дисплей ЖКИ
lcd_gotoxy(0, 1); // Переводим курсор на первый символ первой строки
lcd_puts(_str_2); // Выводим строку _str на дисплей ЖКИ
delay_ms(900); // ждём 900мс
lcd_clear(); // чистим дисплей перед выводом
lcd_init(16); // Инициализация ЖКИ на 16 символов
ну стоит убрать повторную инициализацию и очистку, в остальном вроде должно работать
Скажите, а про функцию sprinf где можно почитать? Я задавал уже вопрос, как расшифровать строку, немного не доходит.
Здравствуйте, у меня проблемка. В протеусе при симуляции вместо градусов С, появляется непонятный символ, прошивку попробовал повторить с вашего кода, загружаю в протеус ваш hex файл, все нормально, потом пробую свой, снова появляется этот символ, пропадает после того, как я ставлю в прошивке между xdf и С пробел.
Здравствуйте,подскажите,можно ли использовать 10 датчиков одновременно,и какие изменения по коду в сравнении с 2 мя?
лично не пробовал, но большой разницы не вижу
Добрый день!
Подскажите, как на Вашем примере который на семисегментнике вывести минусовую температуру?
проверяете что температура меньше нуля if(temper < 0) и выводите знак минуса PORTx.X = 1
Со знаком минус понятно, саму температуру минусовую не показывает, показывает 00.
Там в самой первой версии статьи была хрень с if(temper<0) temper - 4096 или что то вроде того. Это нужно убрать
Можно в прошивке прописать так, чтобы например при включении тумблера, на табло увеличивалась (уменьшалась) температура ?
можно
был бы очень благодарен, если скинули прошивку с увеличением (уменьшением) температуры на табло.
ADMIN, СКИНЕШЬ ТЕКСТ В ПРОШИВКУ ?
AHuKeY, поймите правильно, материал на сайте выложен не для того, чтобы взять и сразу заработало, а для того чтобы вы могли чему то научиться.
На примере использования двух датчиков попробовал вывести показания не в строку, как у вас, а в столбцы, но не могу при этом реализовать функцию lcd_clear(); 🙁
пример кода:
#include
#include
#asm
.equ __w1_port=0x18 ;PORTB
.equ __w1_bit=0
#endasm
#include
#include
#include
unsigned char ds18b20_devices;
unsigned char ds18b20_rom_codes[2][9];
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include
float temper_1;
float temper_2;
void main(void)
{
char lcd_buffer[64];
DDRA=0b00000011;
ds18b20_devices=w1_search(0xf0,ds18b20_rom_codes);
ds18b20_init(&ds18b20_rom_codes[0][0],-10,60,DS18B20_12BIT_RES);
ds18b20_init(&ds18b20_rom_codes[1][0],-30,100,DS18B20_12BIT_RES);
lcd_init(16);
while (1)
{
{
{
temper_1=ds18b20_temperature(&ds18b20_rom_codes[0][0]);
sprintf(lcd_buffer,»T1=%.1f\xdf»,ds18b20_temperature(&ds18b20_rom_codes[0][0]));
lcd_gotoxy(0,0);
lcd_puts(lcd_buffer);
};
{
temper_2=ds18b20_temperature(&ds18b20_rom_codes[1][0]);
sprintf(lcd_buffer,»T2=%.1f\xdf»,ds18b20_temperature(&ds18b20_rom_codes[1][0]));
lcd_gotoxy(0,1);
lcd_puts(lcd_buffer);
};
}
if(temper_1 = 2)
{
PORTA.0=0;
}
if(temper_1 3)
{
PORTA.1=1;
}
if(PORTA.0==1)
{
lcd_gotoxy(0,2);
lcd_puts(«Heat»);
}
if(PORTA.0==PORTA.1)
{
lcd_gotoxy(0,2);
lcd_puts(«Rest»);
}
if(PORTA.1==1)
{
lcd_gotoxy(0,2);
lcd_puts(«Cold»);
}
}
}
если переваливает за отрицательную температуру,то после возвращения из нее, на дисплее появляется второй знак градусов.
извините, разобрался сам 🙄
AHuKeY, если вам на контрольную то ладно. а если для себя то зачем мучаете? скорее для контрольной. тогда зачем учитесь если не понимаете?
Как избавится от периодических глюков? на примере двух датчиков? на дисплее иногда то на одном датчике -9999 появляется, а иногда на втором та же песня.
Обсуждалось много раз, проблема в том, что когда датчик измеряет, если происходит прерывание, то температура не считывается.
Я читал комментарии по этому вопросу, но пока не додумался как это программно реализовать на моем примере 😕 , буду думать 😮
гасить динамическую индикацию или сделать статическую индикацию… в общем вариантов море.
у меня LCD дисплей 🙁 нужно как-то сделать, что бы при прерывании датчика, контроллер запомнил последнее измеренное значение температуры, и даже при отключении датчика не обновлялся, а обновлялся только при подключенном датчике, типа «если датчика нет, то сохранять последнее измеренное значение, и руководствоваться только им», if(?),то {?} , с этой функцией и возникают сложности. 😥
еще хочу добавить, что у меня просто обыкновенный термостат, там нет никаких компараторов или внешних и прочих прерываний, просто при заданных константных значениях температуры включаются две ножки контроллера, вот пример кода:#include
#include
#include
#include
#include
unsigned char ds18b20_devices;
unsigned char ds18b20_rom_codes[2][9];
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include
float temper_1;
float temper_2;
void main(void)
{
char lcd_buffer[64];
DDRA=0b00000011;
ds18b20_devices=w1_search(0xf0,ds18b20_rom_codes);
ds18b20_init(&ds18b20_rom_codes[0][0],-55,100,DS18B20_12BIT_RES);
ds18b20_init(&ds18b20_rom_codes[1][0],-55,100,DS18B20_12BIT_RES);
lcd_init(16);
while (1)
{
#asm(«cli»)
temper_1=ds18b20_temperature(&ds18b20_rom_codes[0][0]);
temper_2=ds18b20_temperature(&ds18b20_rom_codes[1][0]);
#asm(«sei»)
delay_ms(1000);
lcd_clear();
lcd_gotoxy(0,0);
sprintf(lcd_buffer,»t1=%.1f\xdf\C»,temper_1);
lcd_puts(lcd_buffer);
lcd_gotoxy(0,1);
sprintf(lcd_buffer,»t2=%.1f\xdf\C»,temper_2);
lcd_puts(lcd_buffer);
if(temper_1 = 2)
{
PORTA.0=0;
}
if(temper_1 3)
{
PORTA.1=1;
}
if(PORTA.0==1)
{
lcd_gotoxy(0,2);
lcd_puts(«Heat»);
}
if(PORTA.0==PORTA.1)
{
lcd_gotoxy(0,2);
lcd_puts(«Rest»);
}
if(PORTA.1==1)
{
lcd_gotoxy(0,2);
lcd_puts(«Cold»);
}
}
}
еще вопрос, на некоторых сайтах можно найти библиотеки для новых версий CVAVR,называются lcd_rus, типа можно без прагм использовать русскую символику на lcd, однако когда я пробовал нечто подобное подключать, то в протеусе оно не работало, дисплей вообще ничего не отображал, рабочие ли вообще эти библиотеки?!
тогда сложно сказать почему 9999, может в железяке проблема. в протеусе8 были добавлены русские символы.
мне на контрольную надо. очень.
при вкл тумблера на табло увелич темп.
AHuKeY, а если викл. тумблер то что?
AHuKeY, какая то интересная контрольная у вас. для начала условия вашей задачи, езе не понятно зачем тумблером менять значения от датчика или условия или что????
Вообщем.
К этой схеае добавлен тумблер к ножке РВ0.
При вкл тумбл — на табло темп увелич, при откл тумбл — ничего не происходит.
Датчиком регулировать ничего нельзя.
Какая прошивка ну или эта часть.
Спасибо заранее.
AHuKeY, идем дальше. что у вас не получаетьс я или что не понятно ? у вас есть какие то идейки?
Темп не увелич.
Что только не прописывал.
Вроде бы просто, но у ввех спрашивал — не получается все равно.
напишите кусок кода где вы увели. темп. тумблером.
я говорю, что мне надо этот кусок.
Вот ссылки, что необходимо сделать мне на контрольную. Буду благодарен, если кто скажет, как все-таки прописать в CodeVis в прошивке код, чтобы увеличивалась температура на табло.
Вот фото скриншотов:
http://pixs.ru/showimage/nachalojpg_8279178_21628529.jpg
http://pixs.ru/showimage/konecjpg_5170914_21628545.jpg
Ты по ходу вообще нечего не можеш понять. Я например могу сделать так что температура сохраниться текущая при начале использования тумблера, или же температ. дальше будет измерять но температура будет прибавляться на 1 еден. при использовании тумблера.
Но есть одно но, зачем мне это писать? у меня другие задачи есть. Ты даже свой вариант не предложил, это значит ты вообще не можеш понять в чем суть. Вот к чему приводит использования готовых библиотек не поняв ее. Кстати где такие контрольные дают?
Вся понятно.
Вопросов к тебе больше нет.