logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

ds1820 i dziwne odczyty mimo CRC (pomoc za punkty!!!)

dturczak 05 Sie 2007 17:52 1821 10
REKLAMA
  • #1 4148675
    dturczak
    Poziom 19  
    Posty: 416
    Pomógł: 9
    Ocena: 5
    dalem korekcje CRC i czas miedzy pomiarami 1s..
    gdy oziebiam schodzi do 11.5 i koniec ...
    crc nie przepuszcza dalej chyba w takim razie..
    od czasu do czasu pojawiaja sie wtedy wyniki przerozne
    27.5 -87.5 +33.0 niewiadomo skad...
    przy starcie pokazuje temperature prawidlowa...
    jak zwiekszam tez (nie probowalem wiecej niz 10 st)
    chociaz przy przycisnieciu palcami temp sie zwieksza tylko kilka stopni
    a jak przyloze cos zimnego dziwnie skacze..tzn <+14 stopni ok..
    pokaze wartosci,70,80... na przemian z wartoscia prawidlowa...
    w ten sposob ze ledwo co widac...
    oto caly kod.. jakby ktos mogl zerknac..no wiem ze kolejny raz ds1820
    moze ktorych z opoznien jest za male dla nizszych temperatur...
    wogole wydaje mi sie ze źle przetwarzam ujemna temperature..
    bardzo prosze o o pomoc..
    jestem w stanie dac troche punktow
    Kod:
    
    #include <avr/io.h> 
    #include "delay.h" 
    char bajt[8]; 
    char nr; 
    void licz_CRC(char bajt,unsigned char *CRC)      //procedura wyliczania CRC 
    {                  //wielomian generujący jest równy: x^8 + x^5 + x^4 + 1 
     unsigned char zp1,zp2,i;    //zmienne pomocnicze 
    
     zp1=bajt; 
     for(i=0;i<8;i++) 
     { 
      bajt^=*CRC;           //wskaźnik *CRC wyznacza aktualnie wyliczony CRC 
      zp2=bajt&0x01;        //wydzielenie bitu do obliczeń 
      bajt=*CRC; 
      if(zp2) 
      { 
       bajt^=0x18; 
      } 
      bajt=((unsigned char)(bajt)>>1)+0x80*zp2; //konwersja uch jest potrzebna do 
                                                //prawidłowego wykonania przesunięcia 
      *CRC=bajt; 
      zp1=(bajt=zp1>>1);    
     } 
    } 
    
    void instrukcja1w(unsigned char instr) 
    { 
       unsigned char i; 
       unsigned char znak; 
          for(i=0;i<8;i++) 
          { 
             znak=instr & _BV(i); 
             if(znak) 
             { 
                DDRD|=_BV(6); 
                delay_us(11); 
                DDRD&=~_BV(6); 
                delay_us(60); 
             }else{ 
                DDRD|=_BV(6); 
                delay_us(70); 
                DDRD&=~_BV(6); 
             } 
    
          } 
    
    } 
    
    void czytaj1w_temp() 
    { 
       unsigned char znak; 
       unsigned char temp_calk; 
       unsigned char temp_ulam; 
       unsigned char bit; 
       unsigned char l; 
       unsigned char i; 
    
        temp_calk=0x00; 
    
       for(l=0;l<9;l++) //kolejny z 2 bajtow 
       { 
          for(i=0;i<8;i++) //kolejny z 8 bitow 
          { 
             DDRD|=_BV(6); 
             delay_us(1); 
             DDRD&=~_BV(6); 
             delay_us(14); 
             if(bit_is_clear(PIND,6)) bit=0; else bit=1; 
             delay_us(60); 
              
             if ((l==0) && (i==0)) //ulamek 
             { 
                if (bit==0) temp_ulam=".0"; else temp_ulam=".5"; 
             } 
    
             if ((l==0) && (i>0)) //calkowita 
             { 
                if (bit==0) temp_calk&=~_BV(i-1); else temp_calk|=_BV(i-1); 
             } 
    
             if (l==1) //znak 
             { 
                if (bit==0) znak&=~_BV(i); else znak|=_BV(i); 
             } 
    
             if (bit==0) bajt[l]&=~_BV(i); else bajt[l]|=_BV(i); 
    
          } 
           
    
       } 
       //jezeli ujemna 
          if (znak==0xFF) 
          { 
             temp_calk=((~temp_calk)|0x01); 
             znak="-"; 
          }else 
          { 
             znak="+"; 
          } 
       //wyswietlanie 
      unsigned char zp; 
       zp=0;           //w zp będzie liczone CRC - wstępne zerowanie 
       for(i=0;i<9;i++) 
       { 
        licz_CRC(bajt[i],&zp);     //licz CRC ze wszystkich bajtów odebranych 
       } 
    if (zp==0){ 
          //liczba calkowita 
          unsigned char temp1; 
          unsigned char temp2; 
          unsigned char wynik; 
          unsigned char bajt_j; 
          unsigned char bajt_dz; 
    
          tekst(znak); 
            //temp1=temp_calk & 0x0F;    
            //temp2=(temp_calk>>4) & 0x0F; 
          //temp2=temp2*16; 
            //wynik=temp1 + temp2; 
          wynik=temp_calk; 
    
            bajt_j=wynik % 10; 
            wynik=wynik/10; 
            bajt_dz=wynik % 10; 
    
            bajt_j= bajt_j  + 48; 
            bajt_dz=bajt_dz + 48; 
           
          dana(bajt_dz); 
          dana(bajt_j); 
          //char string[16]; 
          //utoa(temp_calk,string,16); 
            //tekst(string);    
    
          //tekst(temp_calk); 
          //koniec liczby calkowitej 
    
          tekst(temp_ulam); 
       } 
    
    
    } 
    unsigned char reset1w() 
    { 
       unsigned char jest; 
       jest=0; 
        DDRD|=_BV(6); 
       delay_us(480); 
       DDRD&=~_BV(6); 
       delay_us(65); 
       if(bit_is_clear(PIND,6)) jest=1; 
       delay_us(415); 
       if(bit_is_clear(PIND,6)) jest=0; 
       return jest; 
    } 
    
    
    int main(void) //program główny 
    { 
    
    
     DDRA|=_BV(LCD_LED_PIN); 
     PORTA|=_BV(LCD_LED_PIN); 
    
     PORT_DB6|=_BV(PIN_DB6); 
     PORT_DB7|=_BV(PIN_DB7); 
    
     DDRC|=_BV(PIN_RS); 
     DDRC|=_BV(PIN_E);    
     DDRC|=_BV(PIN_DB4); 
     DDRC|=_BV(PIN_DB5); 
     DDRD|=_BV(PIN_DB6); 
     DDRA|=_BV(PIN_DB7); 
    
     DDRD &=~_BV(6); 
     PORTD&=~_BV(6); 
    
     ini_lcd(); 
    
         instrukcja(0x0c); //0f 
        instrukcja(0x01); 
        instrukcja((0*0x40+0)|0x80); 
        //tekst("poczatek"); 
        //instrukcja((1*0x40+0)|0x80); 
        //tekst("2'ga linia :P"); 
    
     while(1)    
      { 
    
     delay_us(1000000); 
       if(reset1w()) 
       { 
    
        instrukcja((0*0x40+0)|0x80); 
        instrukcja1w(0xCC); //zaadresowanie na wszystkie 
        instrukcja1w(0x44); //konwersja temp. 
         delay_us(600000);    //czas na pomiar 
        reset1w(); 
        
    
        instrukcja1w(0xCC); //readscrable 
    
        czytaj1w_temp(); 
    
       }else{ 
    
        instrukcja((0*0x40+0)|0x80); 
        tekst("Brak pastylki   "); 
       } 
        
        delay_us(1000000); 
    
    
    
     } 
    
    } 
    
    
      
    
  • REKLAMA
  • #2 4149137
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    Chłopie :!:
    Miotasz się jak mucha na lepie, a do dokumentacji DS1820 nie chce Ci się zajrzeć :(
    Powiedz mi , skąd DS ma wiedzieć że chcesz odczytać dane o zmierzonej temperaturze , skoro NIGDZIE w kodzie nie wysyłasz do DS-a polecenia/rozkazu READ SCRATCHPAD :?:
    Poza tym , Twój kod jest strasznie .... "pogmatwany" ;)
    
      instrukcja1w(0xCC); //zaadresowanie na wszystkie
        instrukcja1w(0x44); //konwersja temp.
         delay_us(600000);    //czas na pomiar
        reset1w();
       
    
        instrukcja1w(0xCC); //readscrable SKIP ROM
    
        instrukcja1w(READ_SCRATCHPAD); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    
        czytaj1w_temp();
    
    


    Piotrek
  • REKLAMA
  • #3 4149171
    dturczak
    Poziom 19  
    Posty: 416
    Pomógł: 9
    Ocena: 5
    instrukcja1w(0xBE);
    wykasowalo sie jakos,bo przy edycji posta kasowalem pare linijek .byla tam..
    bez tego ,nic bym przeciez nie odczytal,sorki...
    tak jak mowie,tylko dla temperatur <11 zle sie dzieje...
    dlaczego pogmatwany... napisany podstawowymi funkcjami ;)
  • #4 4149699
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    Skoro tak , to może masz coś nie tak z timingami( delay_us() ) na 1wire :?:

    Piotrek
  • REKLAMA
  • #5 4149710
    dturczak
    Poziom 19  
    Posty: 416
    Pomógł: 9
    Ocena: 5
    chcialbym zeby tylko o to chodzilo
    do opoznien uzywam biblioteki : (zalacznik)
    Załączniki:
    • delay.h (1.61 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #6 4149724
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    Ja też tej używam i u mnie 1wire "chodzi".

    Piotrek
  • #7 4149952
    dturczak
    Poziom 19  
    Posty: 416
    Pomógł: 9
    Ocena: 5
    domyslam sie ze tobie chodzi ;)
    ale myslisz ze kod jest dobry...?
    tzn odczyt z ds1990 przebiega prawidlowo za kazdym razem
    moze wiec zle "przetwarzam" bity ..
    no nie wiem..
    ale masz moze jakies pomysly?
    zmniejszyc rezystor podciagajacy moze albo cos..
    no nie chce sie poddac :P
  • #8 4150238
    sawitar
    Poziom 18  
    Posty: 228
    Pomógł: 20
    Ocena: 19
    Nie pamiętam dokładnie specyfikacji 1wire, ale wydaje mi się ze przy odczycie sprawdzenia stanu bitu nalezy dokonać przed 15 us, a więc linię
    delay_us(14);
    należało by zastąpić
    delay_us(13);

    btw. ten sam błąd jest popełnił Maxim w swoich sterownikach referencyjnych.

    Czy mógłbyś także podać wersję czujnika jakiej używasz
  • REKLAMA
  • #9 4150246
    dturczak
    Poziom 19  
    Posty: 416
    Pomógł: 9
    Ocena: 5
    ok.niezla sugestia ..
    zaraz sprawdzam..
    dzieki za checi zerkniecia w kod.. :)
    DS1820
    050402 136AF
    poczatkowo myslalem ze jakas uszkodzona seria...

    no niestety,czas zmienilem(ustawialem od 10 do 13 us) i nic z tego,widocznie w czym innym problem..
    chociaz wlasciwie troche zaaragowalo..
    temp sie troche lepiej zmienia,nie tak opornie..
    sprobuje inne sprawdzic (hm moze czasy na resecie?)
    program w bascomie dziala bez problemu..
    wiec wydaje mi sie ze jest to wina mojego kodu tylko :(
  • #10 4150852
    sawitar
    Poziom 18  
    Posty: 228
    Pomógł: 20
    Ocena: 19
    Jeśli używasz przerwań to powinieneś na czas zapisu i odczytu je wyłączać. To bardzo ważne!
  • #11 4150909
    dturczak
    Poziom 19  
    Posty: 416
    Pomógł: 9
    Ocena: 5
    nie uzywam przerwan....
    wydaje mi sie ze to cos z czasami jest nie tak ,zmienilem niektore i juz schodzi do pojedynczych stopni..
    moze o jakims zapomnialem?
    jakby ktos mogl je skontrolowac,bylbym wdzieczny...
    teraz co prawda jakos chodzi ale nie moge zejsc ponizej 0 stopni..
    wkladam pastylke do kostki lodu i pokazuje +2 st..
    mozliwe to raczej nie jest co...

Podsumowanie tematu

✨ Dyskusja dotyczy problemów z odczytem temperatury z czujnika DS1820, gdzie pomiary poniżej 11°C są nieprawidłowe, a wyniki są niestabilne i zawierają błędne wartości mimo zastosowania korekcji CRC. Użytkownik stosuje opóźnienia 1s między pomiarami oraz bibliotekę do obsługi magistrali 1-Wire, jednak podejrzewa błędy w przetwarzaniu ujemnych temperatur i ewentualne problemy z timingiem sygnałów, zwłaszcza opóźnieniami rzędu kilkunastu mikrosekund przy odczycie bitów. Zwrócono uwagę na konieczność wysłania polecenia READ SCRATCHPAD do DS1820 przed odczytem danych oraz na poprawne ustawienie czasów opóźnień w funkcji delay_us(), sugerując zmniejszenie opóźnienia z 14 do 13 µs. Poruszono także kwestię wyłączania przerwań podczas komunikacji 1-Wire. Pomimo prób modyfikacji opóźnień i sprawdzenia różnych egzemplarzy czujnika, problem z dokładnym odczytem temperatur poniżej 0°C pozostaje nierozwiązany. Kod jest napisany w języku C dla mikrokontrolera AVR, a użytkownik porównuje swoje wyniki z działaniem programu w Bascomie, gdzie problem nie występuje.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA