Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

DS18B20 + C + cos zle z temperatura

timtom 17 Kwi 2008 20:42 3738 10
  • #1 17 Kwi 2008 20:42
    timtom
    Poziom 9  

    Witam, Posiadam Atmega8 + DS18B20 + wyswietlacz LCD.
    3ci wieczor nie umiem znalezc bledu w mym kodzie odczytajacym temperature. Caly czas pojawia sie 170. Inicjacje przechodzi poprawnie, odczyty niby tez ale pokazuje zla temperatura, naprawde nie mam juz pomyslow co jest nie tak... Prosze o sugestie co mzoe byc nietak. Dziekuje

    Code:

    //KONFIGURACJA PORTOW:
    // E- PORTC-6
    //RS- PORTC-7
    //D4- PORTA-4
    //D5- PORTA-5
    //D6- PORTA-6
    //D7- PORTA-7

    #include <avr/io.h>
    #include <avr\interrupt.h>
    #include <util\delay.h>

    #define jeden 20
    char cyfry[10] = {72,235,82,98,225,100,68,234,64,96};
    char wyswietl=0;
    unsigned char test, tout;
    volatile unsigned char przycisk=0, menu=0;
    volatile unsigned char temp=0;
    volatile unsigned char liczba=0;

    #define F_CPU 8000000ul

    #define sbi(port, bit) (port) |= (1 << (bit))
    #define cbi(port, bit) (port) &= ~(1 << (bit))

    #define WIRE1_PORT PORTD
    #define WIRE1_DDR DDRD
    #define WIRE1_PIN PIND
    #define WIRE1_CONNECT 7


    #define WIRE1_0 sbi(WIRE1_DDR,WIRE1_CONNECT);cbi(WIRE1_PORT,WIRE1_CONNECT); //0 na wyjscie
    #define WIRE1_1 sbi(WIRE1_DDR,WIRE1_CONNECT);sbi(WIRE1_PORT,WIRE1_CONNECT); //1 na wyjscie






    //
    #define LCD  PORTC
    #define LCD2  PORTA
    #define E  6
    #define RS  7
    //
    #define SET_E   LCD |= _BV(E)
    #define CLR_E   LCD &= ~_BV(E)
    //
    #define SET_RS  LCD |= _BV(RS)
    #define CLR_RS  LCD &= ~_BV(RS)



    unsigned char wire1_init(void)
    {
    unsigned char stan=0;
    WIRE1_0;

    _delay_loop_2(1000); //_delay_us(500);
    WIRE1_1;
    _delay_loop_1(0xA0);//_delay_us(60);

    if(bit_is_clear(WIRE1_PIN,WIRE1_CONNECT))
       {
          stan=1;
       }
    _delay_loop_2(600);//_delay_us(300);

    if(bit_is_set(WIRE1_PIN,WIRE1_CONNECT))
      {
          stan+=2;
       }

    return stan;   

    }







    // procedura zapisu pojedynczego bitu
    void wire1_write_bit(unsigned char bit)
    {


        WIRE1_0;
        _delay_loop_2(30);
            if (bit==0)
             {
             _delay_loop_2(120);
             WIRE1_1;




             _delay_loop_2(4);
             }                              // przedluzenie dla zera
            else
             {
             WIRE1_1;
             _delay_loop_2(140);
             }
                                            // jesli 1 koncz i czekaj
    }

    // procedura zapisu bajtu do urzadzenia
    void wire1_write_byte(unsigned char bajt)
    {
    unsigned char i;
           for(i = 0; i<8; i++)
                    {
                    wire1_write_bit(bajt & 0x01);    // wyslij bit zerowy bajtu
                    bajt>>=1;                       // przesun w prawo i tak osiem bitow
                    }         
    }




    // procedura odczytu bitu od urzadzenie 1wire
    unsigned char wire1_read_bit(void)
    {
            unsigned char bit;
            WIRE1_0;
            _delay_loop_2(4);
            WIRE1_1;
            _delay_loop_2(40);
    if(bit_is_clear(WIRE1_PIN,WIRE1_CONNECT))
       {
          bit=0;
       }
    else
       {
          bit=1;
       }
          _delay_loop_2(40);
        return bit;
    }


    //procedura odczytu bajtu z urzadzenia
    unsigned char wire1_read_byte(void)
    {

    unsigned char i;
    unsigned char value = 0;
       for (i=0;i<8;i++)
       {
       if(wire1_read_bit()) value|=0x01<<i;
       }
    return(value);
    }



    // funkcja opóźniająca o x*1ms
    void waitms(char x)
    {
       x*=4;
       unsigned char a, b; // zmnienne licznikowe
       for( ; x > 0; --x) // ta pętla zostanie wykonana x-razy
         for(b = 10; b > 0; --b) // a ta 10 razy
          for(a = 100; a > 0; --a) // natomiast ta 100 razy
          __asm("nop"); // dodatkowa instrukcja opóźniająca o 1 cykl
          // razem to da opóźnienie ok. x * 1ms
          // x od 0 do 255
    }

    // pcodedura zapisu bajtu do wyświetlacza LCD
    // bez rozróżnienia instrukcja/dana
    void write_to_lcd(char x)
    {
       SET_E; // ustaw na E stan wysoki
          LCD2 = ((LCD2 & 0x0F) | (x & 0xF0)); // zapis pierwszej połówki bajtu      //0x0F=00001111, 0xF0=11110000
       CLR_E; // opadające zbocze na E -> zapis do wyświetlacza
       
       SET_E; // ustaw na E stan wysoki
          LCD2 = ((LCD2 & 0x0F) | ((x & 0x0F) << 4)); // zapis drugiej połowki bajtu
       CLR_E; // opadające zbocze na E -> zapis do wyświetlacza
       waitms(1); // czekaj 1ms
    }

    // procedura zapisu instrukcji do wyświetlacza LCD
    void write_command(char x)
    {
       CLR_RS; // niski stan na RS -> zapis instrukcji
       write_to_lcd(x); // zapis do LCD
    }

    // procedura zapisu danej do wyświetlacza LCD
    void write_char(char x)
    {
       SET_RS; // wysoki stan na RS -> zapis danej
       write_to_lcd(x); // zapis do LCD
    }

    // procedura zapisu tekstu do wyświetlacza LCD
    void write_text(char * s)
    {
       while(*s) // do napotkania 0
        {
         write_char(*s); // zapisz znak wskazywany przez s na LCD
         s++; // zwiększ s (przygotuj nastepny znak)
        }
    }

    // procedura inicjalizacji wyświetlacza LCD
    void lcd_init(void)
    {
       waitms(15); // czekaj 15ms na ustabilizowanie się napięcia zasilającego
       CLR_E; // E = 0
       CLR_RS; // RS = 0- czyli tryb komend

       char i; // zmianna licznikowa
       for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
       {
         SET_E; // E = 1
          LCD &= 0x3F; //00111111 (bo zmiany maja byc yno na bitach E i RS)
         CLR_E; // E = 0
         waitms(5); // czekaj 5ms
       }

       SET_E; // E = 1
          LCD &= 0x2E; //00101110
       CLR_E; // E = 0
       waitms(1); // czekaj 1ms

       write_command(0x28); // interfejs 4-bity, 2-linie, znak 5x7         //00101000
       write_command(0x08); // wyłącz LCD, kursor i miganie            //00001000
       write_command(0x01); // czyść LCD                           //00000001
       write_command(0x06); // bez przesuwania w prawo                  //00000110
       write_command(0x0C); // włącz LCD, bez kursora i mrugania         //00001100
    }






    // program główny
    int main(void)
    {

    DDRA=DDRC=255;
       DDRB = 0xFF;
    DDRD=0;
    PORTC=255;
    PORTB = 0xff;

    int i;
    for(i=0; i <100; i++)
    {

    //test=wire1_init();
    //if(test==3)
    //PORTD=0x00;
    test=0;
    wire1_init();

       wire1_write_byte(0xcc);
       wire1_write_byte(0x44);
       while(wire1_read_byte()!=255);
       if(wire1_init()==3)
          PORTD=0x00;
       wire1_write_byte(0xcc);
       wire1_write_byte(0xbe);
       test=wire1_read_byte();   
       wire1_read_byte();
    //   if((test)>200)
       //   PORTB=0x00;
          
       //   PORTD=test;
          
       


       // konfiguracja portów we/wy
       DDRC = 0xC0;   //11000000         //ustawienie E=1 oraz RS=1
       //PORTC = 0xFF;
       DDRA= 0xF0;      //11110000         ustawienie D4=1 oraz D5=1 oraz D6=1 oraz D7=1
       //PORTA= 0xFF;


       // inicjalizacja LCD
       lcd_init();
       char a="LOVE :*";
       int b=95;


       char c[4];
       int h = 65530;
       utoa(test, c, 10);       
       write_text(c);            //TUTAJ WYSWIETLAM TEMPERATURE
       

       waitms(30000);//2s


    }   


       // petla nieskończona
       while(1);         
       
       
       return 0;
    }


    Dziekuje za udzielona pomoc.

    0 10
  • #2 17 Kwi 2008 20:44
    Freddie Chopin
    Specjalista - Mikrokontrolery

    po pierwsze to DS18B20 zwraca temperature w formacie SIGNED char.

    a po drugie, skoro caly czas zwraca to samo, to znaczy ze zle timingi.

    0x41 0x56 0x45!!

    0
  • #3 17 Kwi 2008 21:15
    don diego
    Poziom 32  

    Cytat:
    Code:
     // inicjalizacja LCD 
    
       lcd_init();
       char a="LOVE :*";
       int b=95;


    Prezent dla dziewczyny? ;)

    0
  • #4 17 Kwi 2008 23:31
    datch
    Poziom 12  

    Witam cos mi sie zdaje ze masz zle napisana instrukcje odczytu, bo powinienes robic odczyt po minimum 15us, no chyba ze zle zroumiałem tego delaya tu masz linka z opisem tego ale peniwe i tak juz cos patrzyles http://mikrokontrolery.net/ogolne_1-wire.htm
    wiec ten czas oczekiwania po zmieniniu portu wyjscia na wejscie pownien zajmowac jak najmniej czasu.To sa maoje przypuszczenia.

    0
  • #5 18 Kwi 2008 12:28
    rybol
    Poziom 20  

    opoznienie musi byc min 750ms.. bo inaczej otrzymasz zle wartosci

    0
  • #6 18 Kwi 2008 13:34
    elektryk
    Poziom 42  

    Masz dwie rzeczy do poprawienia
    1. konwersję wartości, 2x za duża wychodzi, powinna być 85*C
    2. timingi, po wysłaniu rozkazu ConverT trzeba wstawić opóźnienie

    0
  • #7 18 Kwi 2008 16:36
    timtom
    Poziom 9  

    Cytat:
    1. konwersję wartości, 2x za duża wychodzi, powinna być 85*C

    OK, dodalem:
    test2= (test>>1);


    Cytat:
    2. timingi, po wysłaniu rozkazu ConverT trzeba wstawić opóźnienie

    Cytat:
    opoznienie musi byc min 750ms.. bo inaczej otrzymasz zle wartosci

    Po dodaniu opoznienia i zmiane interwalow czasowych, podczas inicjalizacji, odczytu zapisu zaczelo mi cos odczytywac. Wartosci faktycznie sie zmiekszaja przy podgrzaniu i sa w miare zblizone do temperatury panujace, zwieksza sie cyfra podczas dotyku czujnika.... jednak 1 mankament: wynik jest podany .... hmmm... w fahrenheitach?? Z DataSheetu do DS18B20 wynika ze zostanie zwrocona wartosc w celcjuszach... takze moze robie nie tak cos?
    Dla pewnosci zamieszam poprawione fragmenty kodu:
    Code:

    unsigned char wire1_init(void)
    {
    unsigned char stan=0;
    WIRE1_0;

    //_delay_loop_2(1000); //
    _delay_us(500);
    WIRE1_1;
    //_delay_loop_1(0xA0);//
    _delay_us(90);

    if(bit_is_clear(WIRE1_PIN,WIRE1_CONNECT))
       {
          stan=1;
       }
    //_delay_loop_2(600);//
    _delay_us(300);

    if(bit_is_set(WIRE1_PIN,WIRE1_CONNECT))
      {
          stan+=2;
       }

    return stan;   

    }







    // procedura zapisu pojedynczego bitu
    void wire1_write_bit(unsigned char bit)
    {


        WIRE1_0;
        //_delay_loop_2(30);
       _delay_us(15);
            if (bit==0)
             {
            // _delay_loop_2(120);
           _delay_us(60);
             WIRE1_1;
             _delay_loop_2(4);
          // _delay_us(2);
             }                              // przedluzenie dla zera
            else
             {
             WIRE1_1;
             //_delay_loop_2(140);
           _delay_us(70);
             }
                                            // jesli 1 koncz i czekaj
    }

    // procedura zapisu bajtu do urzadzenia
    void wire1_write_byte(unsigned char bajt)
    {
    unsigned char i;
           for(i = 0; i<8; i++)
                    {
                    wire1_write_bit(bajt & 0x01);    // wyslij bit zerowy bajtu
                    bajt>>=1;                       // przesun w prawo i tak osiem bitow
                    }         
    }




    // procedura odczytu bitu od urzadzenie 1wire
    unsigned char wire1_read_bit(void)
    {
            unsigned char bit;
            WIRE1_0;
            //_delay_loop_2(4);
          _delay_us(2);
            WIRE1_1;
            //_delay_loop_2(40);
          _delay_us(20);
    if(bit_is_clear(WIRE1_PIN,WIRE1_CONNECT))
       {
          bit=0;
       }
    else
       {
          bit=1;
       }
          _delay_loop_2(40);
         _delay_us(20);
        return bit;
    }


    //procedura odczytu bajtu z urzadzenia
    unsigned char wire1_read_byte(void)
    {

    unsigned char i;
    unsigned char value = 0;
       for (i=0;i<8;i++)
       {
       if(wire1_read_bit()) value|=0x01<<i;
       }
    return(value);
    }



    ORAZ MAIN:
    test=0;
    wire1_init();
       wire1_write_byte(0xcc);
       wire1_write_byte(0x44);
       //while(wire1_read_byte()!=255);
       _delay_ms(850);
       wire1_init();
       wire1_write_byte(0xcc);
       wire1_write_byte(0xbe);
       test=wire1_read_byte();   
       wire1_read_byte();
    //   wire1_read_byte();
    //   if((test)>200)
       //   PORTB=0x00;
          
       //   PORTD=test;
          

    /*
          
          reset_1w();
       send_1w(0xCC);
       send_1w(0x44);
       _delay_ms(500);
       reset_1w();
       send_1w(0xCC);
       send_1w(0xBE);
       T_LSB = get_1w();
       T_MSB = get_1w();
       reset_1w();
    */
       test2= (test>>1);

       // konfiguracja portów we/wy
       DDRC = 0xC0;   //11000000         //ustawienie E=1 oraz RS=1
       //PORTC = 0xFF;
       DDRA= 0xF0;      //11110000         ustawienie D4=1 oraz D5=1 oraz D6=1 oraz D7=1
       //PORTA= 0xFF;


       char c[8];
       int h = 65530;
       utoa(test2, c, 10);       
       write_text(c);   

       


    Cytat:

    Cytat:
    Kod:
    // inicjalizacja LCD
    lcd_init();
    char a="LOVE :*";
    int b=95;





    Prezent dla dziewczyny?


    Po czesci :PP Bo na codizen jestem programista .NET, a projekt z mikroprockow robie z musu uczelnianego, ale pomyslaem ze jak juz cos zrobie to bedzie to cos co dam dziewczynie :P



    Pozdrawiamm

    0
  • #8 20 Kwi 2008 11:26
    timtom
    Poziom 9  

    Jakies pomysly?? Kolejny wieczor nad tym sie meczylem i nic... :/ Pozdr.

    0
  • #9 20 Kwi 2008 14:48
    datch
    Poziom 12  

    mi sie zdaje ze tu jest bład

    Code:

    // procedura odczytu bitu od urzadzenie 1wire
    unsigned char wire1_read_bit(void)
    {
            unsigned char bit;
            WIRE1_0;
            //_delay_loop_2(4);
          _delay_us(2);
            WIRE1_1;
            //_delay_loop_2(40);
          _delay_us(20);
    if(bit_is_clear(WIRE1_PIN,WIRE1_CONNECT))
       {
          bit=0;
       }
    else
       {
          bit=1;
       }
          _delay_loop_2(40);
         _delay_us(20);
        return bit;
    }


    ja bym to poprawił na\
    Code:

    // procedura odczytu bitu od urzadzenie 1wire
    unsigned char wire1_read_bit(void)
    {
            unsigned char bit;
            WIRE1_0;
          _delay_us(2);
            WIRE1_1;
          _delay_us(1);
    if(bit_is_clear(WIRE1_PIN,WIRE1_CONNECT))
       {
          bit=0;
       }
    else
       {
          bit=1;
       }

         _delay_us(60);
        return bit;
    }

    Bo odczyt pownien chyba odbywać sie jak najpredzej po zwolnieniu lini.

    0
  • #10 20 Kwi 2008 16:11
    timtom
    Poziom 9  

    Dalej to samo, mysle ze czujnik reaguje na zmiany temperatur, bo w chwili gdy go podgrzewam temperatura skacze do ponad 100 stopni, a gdy chlodze np. lodem to maleje prawie do 0 stoplni. Takze jest reackaj na temperature, jednak wartosci temperatur nie sa prawidlowe.
    Takze jak juz wiem co jest nie takj, na ktory kawalek kodu powinienem zwrocic uwage? Dziekuje za kolejne wskazowki:)

    0
  • #11 20 Kwi 2008 17:36
    zumek
    Poziom 39  

    timtom napisał:
    Dalej to samo...

    A czemu miało by być inaczej :?:
    Patrząc na Twój kod , dochodzę do wniosku , że:
    a) nie czytałeś dokumentacji DS18B20
    b)czytałeś , ale nie zrozumiałeś
    Dlaczego odczytując dane o temperaturze , odczytujesz tylko 1 bajt :?:
    Pisałem już kilka razy na tym forum , że DS18B20 standardowo zwraca dane w postaci 16-bitowej liczby typu signed int o rozdzielczości 1/16 C.
    Tak np. może wyglądać kod:
    Code:


    #define BYTE_LOW  0
    #define BYTE_HIGH 1
    signed int temperatura;
    char *ptr_to_temperatura=(char*)&temperatura;

    //...
       ptr_to_temperatura[BYTE_LOW]=wire1_read_byte();
       ptr_to_temperatura[BYTE_HIGH]=wire1_read_byte();
       temperatura/=4;     //temperatura całkowita
           
    //...

     char c[4];
       itoa(test, temperatura, 10);       
       write_text(c);            //TUTAJ WYSWIETLAM TEMPERATURE

    To tyle.

    Piotrek

    0
  Szukaj w 5mln produktów