X

DS1820 i niskie temperatury

16 Apr 2006 17:57 PGpgp
  • #1 16 Apr 2006 17:57
    pgp
    Level 19  
    Helpful post? (0)
    Gdy do mojego DS1820 przyblizam coś bardzo zimnego ( z zamrazarki) to zaczyna wariować... Temperatury dochodzą do 140 stopni ... Moze ten czujnik źle reaguje na takie nagłe skoki ? A moze chodzi o wilgoć która sie z tego roztapia... Szkoda ze nie ma zimy - wystawiłbym za okno i przetestował...
  • #2 16 Apr 2006 22:17
    Pituś Bajtuś
    Level 28  
    Helpful post? (0)
    A może po prostu procedura konwersji jest poprawna tyko dla dodatnich temperatur? Wrzuć ten kawałek programu który odczytane dane z czujnika przetwarza na postać widzialną dla człowieka...
  • #3 17 Apr 2006 10:49
    pgp
    Level 19  
    Topic author Helpful post? (0)
    /////////////////////////////////////////////// czujnik temperatury - funkcje /////////////////////////////

    // OW_RESET - performs a reset on the one-wire
    // returns the presence detect. Reset is 480us Presence
    // another 70us later

    unsigned char ow_reset(void) // reset lini one wire
    {
    unsigned char presence=1;
    sbi(DDRD,3); //DQ = 0; //pull DQ line
    delay(245); // wystawienie na czas 490us "0" na linię 1w przez uC
    cbi(DDRD,3); //DQ = 1; // allow line to //powrót lini 1w do trybu wejścia
    delay(35); // wait for presence pulse(pochodzący od DS-a) //czekamy na ustabilizowanie lini
    if(bit_is_clear(PIND,3)) presence=0; //odczytujemy co wystawił na linię DS
    //get presence

    delay(220); // wait for end
    return(presence); // presence signal
    } // 0=presence, 1 = no part

    ///---------------------------------------------------------

    // READ_BIT - reads a bit from the one-wire bus. The delay
    // required for a read is 15us, so the DELAY routine won't work.
    // We put our own delay function in this routine in the form of a
    // for() loop.
    unsigned char read_bit(void)
    {
    unsigned char presence;
    sbi(DDRD,3); //DQ = 0; // pull DQ low to start timeslot

    cbi(DDRD,3);//DQ = 1; // then return high
    delay(10); // delay 20 us from start of timeslot
    if(bit_is_clear(PIND,3)) presence=0;
    if(bit_is_set(PIND,3)) presence=1;
    return(presence); // return value of DQ line
    }
    ///---------------------------------------------------------

    void write_bit(char bitval) //WRITE_BIT - writes a bit to the one-wire bus, passed in bitval.
    {
    sbi(DDRD,3); //DQ = 0; // pull DQ low to start timeslot
    if(bitval==1) cbi(DDRD,3); //DQ =1; // return DQ high if write 1
    delay(52); // hold value for remainder of timeslot - delay 104us
    cbi(DDRD,3);//DQ = 1;
    }

    ///---------------------------------------------------------

    unsigned char read_byte(void) // READ_BYTE - reads a byte from the one-wire bus
    {
    unsigned char i;
    unsigned char value = 0;
    for (i=0;i<8;i++)
    {
    if(read_bit()) value|=0x01<<i; // reads byte in, one byte at a time and then
    delay(61); // shifts it left wait for rest of timeslot
    }
    return(value);
    }

    ///---------------------------------------------------------

    void write_byte(char val) // WRITE_BYTE - writes a byte to the one-wire bus.
    {
    unsigned char i;
    unsigned char temp;
    for (i=0; i<8; i++) // writes byte, one bit at a time
    {
    temp = val>>i; // shifts val right 'i' spaces
    temp &= 0x01; // copy that bit to temp
    write_bit(temp); // write bit in temp into
    }
    delay(52);
    }

    ///---------------------------------------------------------

    void Read_Temperature(void)
    {
    char tmp[10];
    char temp_lsbyte,temp_msbyte;
    int k;
    cli(); //wyłączenie przerwań
    if(!ow_reset())
    {
    write_byte(0xCC); //Skip ROM
    write_byte(0x44); // Start Conversion
    delay(52);
    ow_reset();
    write_byte(0xCC); // Skip ROM
    write_byte(0xBE); // Read Scratch Pad

    for (k=0;k<9;k++){tmp[k]=read_byte();}

    temp_msbyte = tmp[1]; // Sign byte + lsbit
    temp_lsbyte = tmp[0]; // Temp data plus lsb
    if (temp_msbyte <= 0x80){temp_lsbyte = (temp_lsbyte/2);} // shift to tmp whole degree
    temp_msbyte = temp_msbyte & 0x80; // mask all but the sign bit
    if (temp_msbyte >= 0x80) {temp_lsbyte = (~temp_lsbyte)+1;} // twos complement
    if (temp_msbyte >= 0x80) {temp_lsbyte = (temp_lsbyte/2);}// shift to tmp whole degree
    if (temp_msbyte >= 0x80) {temp_lsbyte = ((-1)*temp_lsbyte);} // add sign bit

    if(temperature!=temp_lsbyte) {temperature=temp_lsbyte; zmtemp=1;}
    }

    sei(); //włączenie przerwań
    }

    Dodano po 4 [minuty]:

    aha, oto zmienna globalona w której przechowuje wartosć temperatury:

    volatile signed char temperature=0; //aktualna temperatura
    i zmienna globalna która mówi czy temperatura sie zmieniła:
    char zmtemp; //zmienna mówiące o zmianie temperatury

    jesli zmienna ta ma wartość jeden (co oznacza zmianę temperatury w stosunku do ostatniego pomiaru to w petli main :

    if(zmtemp==1) //sprawdzenie czy temperatura uległa zmianie od ostatniego pomiaru
    {
    printf("%d",temperature);
    zmtemp--;
    pisztekst("oC");
    }
  • #4 17 Apr 2006 11:36
    elektryk
    Level 42  
    Helpful post? (0)
    Skąd masz taką zakręconą procedure? DS1820 zwraca wynik w postaci liczby U2, wystarczy ją zapisać do zmiennej signed i już masz wszystko gotowe.
  • #5 17 Apr 2006 12:35
    pgp
    Level 19  
    Topic author Helpful post? (0)
    No z noty katalogowej dallasa. Możesz mi z grubsza napisać ta procedurke ?
  • #6 17 Apr 2006 14:26
    zumek
    Level 39  
    Helpful post? (0)
    pgp wrote:
    No z noty katalogowej dallasa. Możesz mi z grubsza napisać ta procedurke ?

    Może warto czasem użyć szukaj ? .

    Piotrek

    PS
    Wprawdzie dotyczy DS18B20 , ale możesz dostosować do swojego ;)
  • #7 17 Apr 2006 15:34
    pgp
    Level 19  
    Topic author Helpful post? (0)
    Zmodyfikowałem trochę procedurę odczytu. Rezygnuję z temperatur ujemnych dla uproszczenia - zatem odczytuję tylko pierwszy bajt. no i zrobiłem sobie funkcję która wyrzuca ten bit na LCD. Okazuje sie ze raz na jakiś czas występują przekłamania pojedynczych bitów... wtedy temperatura wzrasta o 64, 32 , 16, 8 itd... stopni. Myślicie ze to wina że urządzenie jest na płytce uniwerslanej, a nóżki czujnika sa nieprzciete - takie długie jak oryginalne - to prototyp. Może gdybym skrócił nóżki, zrobił jakąś obudowe metalową (ekran) to nie byłoby tych przekłamań... Stworzyłem funkcję która odrzuca nagłe wzrosty/malenia temperatury o więcej niż 8 stopni. Jeśli natomiast stan taki występuje przez 4 pomiary z rzedu (a pomiary wykonuję co sekundę) to przyjmuję tą "dziwnie większą/mniejsza wartość" jako prawdziwą.... Póki co sprawuje się nieźle... No czasami są przekłamania o 4 stopnie... choc urządzenie ma służyc do sterownika ogrzewania wiec chyba zmniejsze próg z 8 do 4 stopni,bo wydaje mi się ze nie jest możliwe żeby w ciągu 1 sek. temp. zmieniła się o 4 stopnie... A oto funkcja :

    void Read_Temperature(unsigned char x)
    {
    char tmp,temp_lsbyte,licz;
    int k;
    cli(); //wyłączenie przerwań
    if(!ow_reset())// czy czujnik odpowiedział na reset?
    {

    write_byte(0xCC); //Skip ROM
    write_byte(0x44); // Start Conversion
    delay(52);
    ow_reset();
    write_byte(0xCC); // Skip ROM
    write_byte(0xBE); // Read Scratch Pad

    tmp=read_byte();
    temp_lsbyte = tmp; // Temp data plus lsb
    temp_lsbyte = (temp_lsbyte/2); // shift to tmp whole degree


    if(temperature!=temp_lsbyte) //sprawdzenie czy nastapiła zmiana od ostatniego pomiaru
    {
    if( ((temp_lsbyte-temperature)<x)||((temperature-temp_lsbyte)<x) ) {temperature=temp_lsbyte; zmtemp=1;licz++; }//jesli zmiana jest wieksza/mniejsza od x stopni - odrzucamy ją
    if(licz==4) {temperature=temp_lsbyte; licz=0; } //jeśli cztery razy pod rząd odczytamy temperaturę dziwnie wyzsza/nizsza
    }
    else {licz=0;}


    }

    sei(); //włączenie przerwań
    }
  • #8 17 Apr 2006 16:00
    zumek
    Level 39  
    Helpful post? (0)
    Nie napisałeś z jaką częstotliwością taktujesz uC , ale jeśli jest to >1MHz to...
    Code:

    unsigned char read_bit(void)
    {
    unsigned char presence;
    sbi(DDRD,3); //DQ = 0; // pull DQ low to start timeslot
    //****może w tym miejscu dodać delay(1) ?????
    cbi(DDRD,3);//DQ = 1; // then return high
    delay(10); // delay 20 us from start of timeslot
    if(bit_is_clear(PIND,3)) presence=0;
    if(bit_is_set(PIND,3)) presence=1;
    return(presence); // return value of DQ line
    }

    ... może dodaj zwłokę pomiędzy sbi i cbi , ponieważ przy zapoczątkowaniu timeslot-u , stan niski na DQ powinien trwać >1uS , a przy taktowaniu uC np. 8MHz raczej tak nie jest :(
    Spróbować warto ;)

    Piotrek

    PS
    Długość nóżek DS-a nie ma tu nic do rzeczy , ale sposób jego zasilania - jak najbardziej ma.
  • #9 23 Apr 2006 00:07
    pgp
    Level 19  
    Topic author Helpful post? (0)
    Zrobiłem tak jak mówisz - dodałem tergo delay'a , ale to powoduje błąd - temperatura jest wtedy 127 st C....
Mouser  Search 4 million + Products
Browse Products