Содержание
Урок 1. Первый проект
Урок 2. Управление кнопками
Урок 3. Подключение LCD
Урок 4. Использование ШИМ
Урок 5. Таймеры
Урок 6.1. Статическая индикация
Урок 6.2. Динамическая индикация
Урок 7.1. Генерация звука
Урок 7.2. Генерация звука. Продолжение
Урок 8.1. Передача данных через UART
Урок 8.2. Передача данных через UART. Продолжение»
Урок 9. Передача данных через SPI
Урок 10. Изучение АЦП. Простой вольтметр
Урок 11. Получение синуса при помощи ШИМ
Урок 12. Измерение температуры
Урок 13. Внешние прерывания.
Урок 14. Использование отладчика
Урок 15.1. Управление инкрементальным энкодером
Урок 15.2. Управление громкостью, при помощи энкодера
Урок 16. Управление RGB светодиодом
Урок 17. Использование ИК
Урок 18.1. Знакомство с графическим дисплеем
Урок 18.2 Вывод изображения на графический дисплей
Урок 18.3 Вывод русскоязычного текста
Урок 19. Формирование сигнала, при помощи ЦАП (R2R)
Урок 20. Опрос матричной клавиатуры
Урок 21. Сторожевой таймер
Урок 22.1 Воспроизведение wav. Введение.
Урок 22.2 Воспроизведение wav. Продолжение.
Урок 23.1 Работа с внешней памятью
Урок 23.2 Работа с файловой системой Fat

termoПродолжаем осваивать периферию, на очереди измерение температуры. Рассмотрим вариант измерения, при помощи датчика температуры DS18b20.

Характеристики датчика: диапазон измерения от -55 до +125°С. Точность измерения ±0,5°С гарантируется в диапазоне от -10 до +85°С. Возможность измерения с разрешением 9, 10, 11 и 12 бит, т.е. с шагом 0,5; 0,25; 0,125; 0,0625°С. Для обмена информацией с AVR микроконтроллером используется 1-Wire протокол. Каждый датчик имеет свой уникальный адрес, поэтому имеется возможность посадить на шину сразу несколько датчиков.

les12-2

Для сборки схемы понадобится жк дисплей, датчик и резистор на 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 — вывод на экран значка градуса.

В результате должно получиться нечто похожее
les12-4

Отрицательной температуры поблизости не было :D, поэтому попробовал остудить бутылочкой соуса из холодильника, результат что то не сильно впечатлил.
les12-5

Зато от нагрева рукой, температура довольно быстро повысилась.
les12-3
Проект доступен тут
Проект для DS18s20
Проект для двух датчиков
Проект для DS18b20 на семисегментниках
Проект Алексея(Alyes)для Atmega16 и шести сегментов + бонус видео устройства

259 комментариев: Урок 12. Измерение температуры при помощи AVR. Простой термометр на AVR.

  • Видимо плохо читали, ответ на Ваш вопрос там есть.
    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 еден. при использовании тумблера.

  • Но есть одно но, зачем мне это писать? у меня другие задачи есть. Ты даже свой вариант не предложил, это значит ты вообще не можеш понять в чем суть. Вот к чему приводит использования готовых библиотек не поняв ее. Кстати где такие контрольные дают?

  • Вся понятно.
    Вопросов к тебе больше нет.

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Последние комментарии
  • Загрузка...
Счетчик
Яндекс.Метрика