Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

DWA(!) termometry DS18B20 + ATmega8 + GCC

kiuba 07 May 2007 16:44 2237 6
  • #1
    kiuba
    Level 9  
    Kombinuję z programem obsługującym DWA termometry DS18B20. Używam ATmegi8 i programuję pod C.
    Chodzi o odczytywanie temperatury na dwóch magistralach onewire - dwóch pinach.

    Przerobiłem standardową, powszechną bibliotekę do obsługi DS18B20 zmieniając to, że normalnie adres bitu portu magistrali 1W jest definiowany jako makro, a ja zrobiłem z tego parametr, z którym to wywoływana jest funkcja: odczytaj_temp(int bitportu) i pozostałe funkcje typu reset1w itd.
    Niestety - drugi odczytywany termometr pokazuje niestabilne około 40stopni (w warunkach pokojowych)..
    Długo już z tym walczę i nie wiem co jest :/

    Zamieniałem DS'y miejscami - nic.
    Dawałem delay'a pomiędzy odczyt1 a odczyt2 - nic.
    Zmieniałem i zamieniałem bity i porty - nic.

    Nieprawidłowy odczyt jest z drugiego odczytywanego, bez względu na to, który to jest DS i na których są bitach portu.

    Dajcie znać jaką macie matodę na odczytywanie dwóch termometrów bo ja już nie mogę:cry:

    Dzięki!
    kuba
    Ethernet jednoparowy (SPE) - rozwiązania w przemyśle. Szkolenie 29.09.2021r. g. 11.00 Zarejestruj się za darmo
  • #2
    Wilku
    Level 17  
    Nie wkleiłeś kodu więc można gdybać. A przypadkiem nie używasz tych samych zmiennych do przechowywania/przeliczania temperatury? Do odczytu kilku DS używam timera według algorytmu:
    init_ds1, po 20ms(przykładowo) init_ds2, po 800ms odczyt_ds1, po 820ms odczyt_ds2, po 1000ms zeruj czas i od nowa. Temperaturę trzymam oczywiście w osobnych zmiennych (trochę tego RAM-u jest w AVR więc można szaleć).
  • #3
    kiuba
    Level 9  
    Code:

    int a=odczytaj_temp(0);
    int b=odczytaj_temp(1);

    zmienna, którą jest raz 0, raz 1 bit portu - w ten sposób go zmieniam.
    Opisałem to w pierwszym poście.

    Wilku, trochę nie rozumiem, że najpierw reset1, potem reset2, potem odczyt1, potem odczyt2. Na pewno używasz dwóch osobnych magistral 1W?
    Myślałem, że jak już (i tak jest siłą rzeczy u mnie) powinno być:
    restet1 -> odczyt1 -> restet2 -> odczyt2
    Pozdrawiam.

    Dodano po 1 [godziny] 36 [minuty]:

    łopatologicznie zduplikowałem bibliotekę ds18b20 i powstało:
    reset_wire1(){......
    reset_wire2(){......
    odczytaj_temp1(){......
    odczytaj_temp2(){......
    .................................
    .................................
    oraz dwa makra:
    #define ONEWIRE1 0
    #define ONEWIRE2 1

    ta sama straszna historia - drugi odczytywany ma o 10stopni za dużo :|
    Dajcie znać jak Wy to robicie, bo ja już nie wiem.
    dzieki.
  • #4
    snow
    Level 29  
    ow_reset1();
    ow_write_byte1(0xCC);
    ow_write_byte1(0x44);
    _delay_ms(250);
    _delay_ms(250);
    _delay_ms(250);
    ow_reset1();
    ow_write_byte1(0xCC);
    ow_write_byte1(0xBE);
    lsb1 = ow_read_byte1();
    msb1 = ow_read_byte1();


    I tak samo dla drugiego, po czym skladam sobie pod dwie zmienne te dwie temperatury uzyskane z czujników.
  • #5
    kiuba
    Level 9  
    -> snow
    bez zmian....
    zrobiłem tak:

    main:
    Code:

    ........................
    ...........................
    wire_reset1();
    wire_write_byte1(0xCC);
    wire_write_byte1(0x44);
    delayms(250);
    delayms(250);
    delayms(250);
    wire_reset1();
    wire_write_byte1(0xCC);
    wire_write_byte1(0xBE);
    lsb1 = wire_read_byte1();
    msb1 = wire_read_byte1();

    temp1 = ((msb1 << 8) | lsb1) * 10 / 16;

     
    wire_reset2();
    wire_write_byte2(0xCC);
    wire_write_byte2(0x44);
    delayms(250);
    delayms(250);
    delayms(250);
    wire_reset2();
    wire_write_byte2(0xCC);
    wire_write_byte2(0xBE);
    lsb1 = wire_read_byte2();
    msb1 = wire_read_byte2();

    temp2 = ((msb1 << 8) | lsb1) * 10 / 16;
    ...............
    .............


    biblioteka ds18b20.h:
    Code:


    unsigned char wire_reset1(void)
    {
            unsigned char potwierdzenie;
            WIRE1_0;                             // reset urzadzenia
            delayus(480);                        // czekaj okolo 500us
            WIRE1_1;
            delayus(70);                         // czekaj okolo 75us

            potwierdzenie = PIN1W & (1<<ONEWIRE1);    // sprawdz bit ONEWIRE11
            potwierdzenie>>=7;                     // zero oznacza OK
                                        // zero wyslane przez urzadzenie
            delayms(1);                         // czekaj okolo 1ms koniec resetu
                                        // po tym czasie powinna wrócic jedynka
       if (potwierdzenie) potwierdzenie=0x00;
            else potwierdzenie=0x01;            // zamien zeby 1 znaczylo OK
       
                                           
            return potwierdzenie;                 // 1 OK; 0 brak urzadzenia

    }

    // procedura zapisu pojedynczego bitu
    void wire_write_bit1(unsigned char bit)
    {
            WIRE1_0;
            asm("nop");
          asm("nop");   
            if (!bit)
          {
          delayus(60);
          WIRE1_1;
          asm("nop");
          asm("nop");
          }
                                            // przedluzenie dla zera
                    else
                {
                WIRE1_1;
                delayus(60);
                }
                                            // jesli 1 koncz i czekaj
    }



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



    // procedura odczytu bitu od urzadzenie 1wire
    unsigned char wire_read_bit1(void)
    {
            unsigned char bit;
            WIRE1_0;
            asm("nop");
          asm("nop");
            WIRE1_1;
            asm("nop");asm("nop");asm("nop");      // 13us
          asm("nop");asm("nop");asm("nop");
          asm("nop");asm("nop");asm("nop");
          asm("nop");asm("nop");asm("nop");
          asm("nop");
            bit =  PIN1W & (1<<ONEWIRE1);
            delayus(80);
            return bit;
    }



    //procedura odczytu bajtu z urzadzenia
    unsigned char wire_read_byte1(void)
    {
    unsigned char bajt, tmp, i;
    bajt = 0;
    for(i = 0;i<8; i++)
            {
                    tmp = wire_read_bit1();
                    tmp = tmp << i;
                    bajt = bajt | tmp;
            }
    return bajt;
    }


              
       
    signed int odczytaj_temp1 (void)
    { signed int t;

             char temp1, temp2;
                         
          wire_reset1();
            wire_write_byte1(0xcc);           // pomin czytanie nr
            wire_write_byte1(0x44);          // nakaz pomiar temperatury
                delayms(100);          // czekaj na przetworzenie 800 dla 12 bitow
          wire_reset1();
          wire_write_byte1(0xcc);           // pomin czytanie nr
          wire_write_byte1(0xbe);           // zadaj odczytania temperatury
           temp1 = wire_read_byte1();    // pierwszy bajt mlodszy
            temp2 = wire_read_byte1();    // drugi bajt starszy
       
                 t = ((temp2 << 8) | temp1) * 10 / 16;
          return(t);
        
        
    }

    .................
    ...............
    ..................


    dalej w tej biblioteece jest wersja dla temp2, czyli reset2, odczyt2...itd.

    Układ zachowuje się zupełnie tak samo, więc plusem jest to, że poprzednie rozwiązanie było tak samo "dobre" ;)
    Ale to, że drugi odczytywany ma taki błąd doprowadza mnie do szału...

    Jakieś pomysły??

    dzieki.
    kuba
  • Helpful post
    #6
    zumek
    Level 39  
    kiuba wrote:

    ...Jakieś pomysły??

    Źle "składasz/sklejasz" odczytany bajt :(
    Code:

    //procedura odczytu bajtu z urzadzenia
    unsigned char wire_read_byte1(void)
    {
    unsigned char bajt, tmp, i;
    bajt = 0;
    for(i = 0;i<8; i++)
            {
                    tmp = wire_read_bit1();
                    tmp = tmp << i;
                    bajt = bajt | tmp;
            }
    return bajt;
    }

    Ja zrobiłbym to tak:
    Code:

    //procedura odczytu bajtu z urzadzenia
    unsigned char wire_read_byte1(void)
    {
    unsigned char bajt, tmp, i;
    bajt = 0;
    for(i = 0;i<8; i++)
            {
                   bajt>>=1;
                   if(wire_read_bit1())  bajt|=0x80;
            }
    return bajt;
    }

    I byłbyś wiedział o tym już dawno , gdybyś nie trzymał kodu "przy orderach" :D

    Piotrek
  • #7
    kiuba
    Level 9  
    Zumek, to ile już masz u mnie browarów? ;)
    Pozdro i dzieki!
pcbway logo