Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

ATMega8 + DS18B20 + LCD | Błąd odczytu 1Wire

ArekBe 05 Dec 2012 21:26 1377 3
  • #1
    ArekBe
    Level 8  
    Witam!

    Mam problem co do odczytu temperatury z czujnika DS18B20. Jest podłączony pod PD7. Wynik to -0.1. Jeżeli odepnę czujnik wynik jest ten sam. Wie ktoś dlaczego ?

    Kod:
    
    ...
    #define WE 7
    #define PORT_1Wire PIND
    #define SET_1Wire DDRD &=~_BV(WE)
    #define CLEAR_1Wire DDRD |=_BV(WE)
    
    char buf[8];
    
    //resetujemy magistrale - czekamy na impuls PRESENCE
    unsigned char RESET_PULSE(void)
    {
    unsigned char PRESENCE;
    CLEAR_1Wire; //ustawiamy magistrale w poziom niski
    _delay_ms(100); //ew. mozna uzyc z biblloteki avr1lbc(avr/ut11) funkcjl _delay_us();
    SET_1Wire; //ustawiamy magistrale w poziom wysoki
    _delay_ms(30); //oczekiwanie na ustawienie llnil w stan niski przez
    //sprawdzamy poziom 11 nil (czy w stanie niskim)
    if (bit_is_clear(PORT_1Wire, WE)) {PRESENCE=1;} else {PRESENCE=0;}
    //1-odebrano bit PREsENcE, 0 - stan nleaktywnosci
    _delay_ms(470); //odczekanie przez mastera 470us 1 spr. czy Ds podclagnal magistrale
    //sprawdzamy poziom linii (czy ustawiona)
    if (bit_is_set(PORT_1Wire, WE)) {PRESENCE=1;
    } else {PRESENCE=0; }
    return PRESENCE; //zwracamy wartosc do funkcji
    } //koniec RESET_PULSE
    
    //wysyla do ukladu pojedynczy bit
    void send(char bit)
    {
    CLEAR_1Wire; //ustawienie w stan niski magistralli
    _delay_ms(5);
    if(bit==1)
    SET_1Wire; //zwolnienie magistralii - wyslanie jedynki
    _delay_ms(80); //przetrzymanie - wyslanie zera sET_Iwire;
    } //koniec send
    
    //zczytuje bit z magistralli
    unsigned char read(void)
    {
    unsigned char PRESENCE=0;
    CLEAR_1Wire;	//ustawienie w Stan niski DQ
    _delay_ms(2); //odczekanie 2u5
    SET_1Wire;	// zwolnienie magistrall
    _delay_ms(15); // delay 15u5
    //odbior jedynki lub zera
    if(bit_is_set(PORT_1Wire, WE)) PRESENCE=1; else PRESENCE=0;
    return(PRESENCE);
    } //koniec read
    
    //wysyla caly bait do ukladu
    void send_byte(char wartosc)
    {
    unsigned char i; //zmienna licznikowa
    unsigned char pom; //zmienna pomocnicza
    for (i=0; i<8; i++)
    {
    pom = wartosc>>i; //przesuniecie bitowe w prawo
    pom &= 0x01; // skoplowanie bitu do zmiennej pomocniczej
    send(pom); // wyslanie bitu na magistrale
    }
    _delay_ms(100); //odczekanie 100us
    } //konlec send_byte
    
    //zczytuje caly bajt z ukladu
    unsigned char read_byte(void)
    {
    unsigned char i; //zmienna licznikowa
    unsigned char wartosc = 0; //zczytywana wartosc
    for (i=0;i<8;i++) //petla wykonywana 8 razy
    {
    if(read()) wartosc|=0x01<<i; //zczytywanie po jednym bicle
    _delay_ms(15); //odczekanie 15 us
    }
    return(wartosc); //zwrot wartoscl do funkcjl
    } //konlec read_byte
    
    //funkcja glowna programu
    int main (void)
    {
    //deklaracja zmiennych lokalnych
    unsigned char sprawdz;
    char temp1=0, temp2=0;
    //inicjalizacja i wyczyszczenie LCD
    lcd_init(); 
    /* Włącza wyświetlanie */ 
    LCD_DISPLAY(LCDDISPLAY);
    LCD_CLEAR;
    lcd_puts("1-wire"); //napis
    _delay_ms(200); //200ms zwloki
    LCD_CLEAR; //wyczyszczenie wyswietlacza
    //petla glowna programu
    for(;;) {
    sprawdz=RESET_PULSE(); //impuls resetu
    if (sprawdz==1)
    {
    send_byte(0xCC); //SKIP ROM
    send_byte(0x44); //CONVERT T
    _delay_ms(200); //odczekaj 750m5 - czas konwersji
    sprawdz=RESET_PULSE(); //wyslanie impulsu reset
    send_byte(0xCC); //SKIP ROM
    send_byte(0xBE); //READ SCRATCHPAD
    temp1=read_byte(); //odczytanie LSB
    temp2=read_byte(); //odczytanie M56
    sprawdz=RESET_PULSE(); //zwolnienie magistrali
    float temp=0; //zmienna do obliczen
    temp=(float)(temp1+(temp2*256))/16; //obl. temp
    dtostrf(temp,1,1,buf); //konwersja float do stringa
    LCD_LOCATE(0,0); //ustawienie w pozycji 0,0
    lcd_puts(buf); //wyswietlenie temp
    _delay_ms(20); //pomiar co 200ms
    }
    else //jesli nie wykryto PRESENCE_PULSE (sprawdz=0)
    {
    LCD_LOCATE(0,0); //pozcyja 0,0 na LCD
    lcd_puts("cisza"); //napis
    }
    }//konlec petli glownej
    } //koniec main()


    Czujnik jest spięty opornikem 4k7: DQ z Vcc.

    Z góry dziękuję i pozdrawiam,
    Arek!
  • Helpful post
    #2
    tehaceole

    Level 28  
    Nie kojarzę już przy jakiej okazji otrzymywałem ten błąd. Ale zaproponować Ci mogę skorzystanie z tych kodów:jeden czujnik, kilka czujników. Kody działają w 100%, pochodzą z wdrożonego rozwiązania. Przyjrzyj się w jaki sposób zrealizowane jest w nich przeliczenie odczytanej z DS wartości na wartość do wyświetlenia.
  • #3
    ArekBe
    Level 8  
    Nie mam pojęcia dlaczego, ale nie mogę otworzyć tych linków tylko mnie gdzieś przekierowuje :c
  • #4
    tehaceole

    Level 28  
    Wybacz Kolego, ale niefortunnie trafiłeś. :) W dniu wczorajszym trwały po południu prace administracyjne nad stroną związane z tym wątkiem. Teraz jest już wszystko ok - a przynajmniej powinno być. :) Ale widzę, że "pomógł" kliknąłeś więc chyba jednak się dostałeś do tych kodów.

    Pozdrawiam