Digitální teploměr s ATmega8

Další jednoduché zapojení určené pro náš kroužek mládeže, tentokrát jednoduchého teploměru s ATmega8 a čidlem teploty DS18B20. Najdete zde kompletní popis programu a zapojení včetně plošného spoje.

Pro správnou funkci teploměru je zapotřebí naprogramovat pojistky mikroprocesoru (fuses). Pojistkami nastavíte, aby mikroprocesor použil jako hodinový signál interní 8 MHz oscilátor, jinak by běžěl na standardní frekvenci 1 MHz a nefungovalo by správně zobrazování teploty. Naše doporučené hodnoty pojistek jsou: hfuse=D9, lfuse=04.

Schéma

Schéma

Plošný spoj

Plošný spoj

Zdrojové soubory

Schéma: eagle, PDF Plošný spoj: eagle, PDF 1:1

Celý projekt: ZIP, TAR.GZ

Projekt na GitLabu digitalni-teplomer-s-atmega8.git

Aktuální zdrojový kód naleznete na našem GitLabu, kde také naleznete přeložený zdojový kód do formátu HEX.

Deska byla vyrobena metodou nažehlením tonneru.

Seznam součástek:

Označení Hodnota Datasheet Odkaz do obchodu
R1 - R8 330 Ω
R9 10 kΩ
R10 4.7 kΩ
C1, C2 100 µF
C3 100 nF
IC1 7805 (TO220) LM7805.pdf tme.eu
IC2 ATmega8A-PU ATmega8a.pdf tme.eu
IC3 DS18B20 DS18B20.pdf tme.eu
D1 LED displej CA56-12SRWA.pdf tme.eu
D2 zenerova dioda 5V6 BZX55C5V6.pdf tme.eu

Fotky

Digitální teploměr Digitální teploměr Digitální teploměr Zapojení DS18B20

Zdrojový kód

Jen hlavní soubor digitalni_teplomer.c, pokud si chcete projekt zkompilovat sami, stáhněte si celý projekt se všemi soubory.

#include <avr/io.h>
#include <avr/interrupt.h>

#include "ds18b20_1.h"
#include "macros.h"

//Definice pozic segmentů na pinech portu
#define _s_A   PD2
#define _s_B   PD0
#define _s_C   PD6
#define _s_D   PD4
#define _s_E   PD3
#define _s_F   PD1
#define _s_G   PD7
#define _s_dot PD5

const unsigned char segs[] = //Definice číslic na 7segmentové displeji
{
    _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F),              //0
    _BV(_s_B) | _BV(_s_C),                                                              //1
    _BV(_s_A) | _BV(_s_B) | _BV(_s_D) | _BV(_s_E) | _BV(_s_G),                          //2
    _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_G),                          //3
    _BV(_s_B) | _BV(_s_C) | _BV(_s_F) | _BV(_s_G),                                      //4
    _BV(_s_A) | _BV(_s_C) | _BV(_s_D) | _BV(_s_F) | _BV(_s_G),                          //5
    _BV(_s_A) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G),              //6
    _BV(_s_A) | _BV(_s_B) | _BV(_s_C),                                                  //7
    _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G),  //8
    _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_F) | _BV(_s_G),                          //9
    _BV(_s_G)                                                                           //mínus
};

const unsigned char err[] = //Chyba
{
    0,                                                          //mezera
    _BV(_s_A) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G),  //E
    _BV(_s_E) | _BV(_s_G),                                      //r
    _BV(_s_E) | _BV(_s_G)                                       //r
};

volatile int temp; //Proměnná pro teplotu

//V tomto přerušení se zobrazuje na despleji
ISR(TIMER1_COMPA_vect)
{
    static int temp_1=0;
    static unsigned char disp=0;
    unsigned char dec;


    disp++;
    if(disp>3) disp=0;          //cyklicky 0 - 4 (sedmisegmentovka)

    PORTD=0xff;                 //vypnout segmenty
    PORTC=0b00100000>>disp;     //přepnout na danou sedmisegmentovku

    if (temp==0x5fff)    //pokud je chyba čidla
    {
        PORTD=(~err[disp]);    //vypsání znaku chyby
    }

    else //pokud není chyba čidla
    {
        switch(disp)
        {
            case 0://1.cifra - znam�nko
                    if (temp>>15) //pokud je nejvyšší bit 1 (záporné číslo)
                    {
                        temp_1=temp*(-1);    //převedení záporné teploty na kladnou
                        PORTD=(~segs[10]);    //zobrazení mínus
                    }
                    else temp_1=temp/16;        //převedení kladné teploty
                break;

            case 1://2.cifra - desítky
                    dec = temp_1 / 10;

                    if(dec>0) PORTD=(~segs[dec]);//zobrazit desítky
                break;

            case 2://3.cifra - jednotky
                    PORTD=(~segs[temp_1 % 10]) & ~_BV(_s_dot); //zobrazit jednotky a desetinnou tečku
                break;

            case 3://4.cifra - desetiny
                    PORTD = (~segs[((temp % 16)*625)/1000]); //zobrazit desetiny
                break;
        }//switch(disp)
    }//else (temp==0x5fff)
}//ISR(TIMER1_COMPA_vect)


int main(void)
{
    DDRD = 0xFF;        //výstupy - segmenty
    DDRC = 0x3F;        //výstupy - displeje

    setb(TCCR1B,0);
    setb(TCCR1B,1);     //start čítače 1 s předděličkou 64
    setb(TCCR1B,3);     //CTC mode

    OCR1AH=0x01;        //porovnávací registry
    OCR1AL=0x39;        //0x0139 = 313 = 8 000 000 / 64 / (100 * 4)  (=> 100 Hz)

    setb(TIMSK,4);      //povolení přerušení od šasovače 1
    setb(SREG,7);       //globální povolení přerušení

    while(1)
    {
         temp=gettemp();//přečtení teploty z čidla
    }
}