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 + lcd + atmega 32 oprogramowanie w C

domelfm 14 Mar 2007 13:11 8516 37
  • #1 14 Mar 2007 13:11
    domelfm
    Poziom 16  

    Witam urzytkowników...
    Programuje juz blisko 4 dni ten mikrokontroler i zero efektu.
    Odczyt zawsze -0.02....
    Dlatego mam prośbę czy ktoś byłby w stanie udostępnić swój działający program na atmege 32 który dobrze czyta temp z ds ?
    Jezeli znajdzie się taki chętny to odrazu zapytam się na jakiej czestotliwosci działa jego atmega ...
    Mam nadzieje że uda mi się to w końcu uruchomic..

    0 29
  • #2 14 Mar 2007 13:50
    rsikon
    Poziom 26  

    Hi hi hi :)

    Kolega zaczyna jak i ja... też jakieś klika dni i ten sam problem :)

    https://www.elektroda.pl/rtvforum/topic713286.html

    Też jak narazie pomocy nie otrzmałem .

    Może napisz na gg do mnie 15179, jak bede mial chwile wolna to odpisze.

    Sai sobie poradzimy jak na nie chca pomoc ;) - mało prawdopodobne.

    Główny problem to odmierzanie mkro sekund . Tak mi się zdaje.

    Radzio

    0
  • #3 14 Mar 2007 15:20
    domelfm
    Poziom 16  

    dobrze Ci się zdaje ..
    Problemem jest czas !!!
    Einstein zaduzo kombinował i nam zakrzywił czasoprzestrzen to wszystko jego wina.... :)

    A tak naprawde to bede wdzięczny za dobre procedurki do i-wire oraz i2c wraz z dobrym odmierzaniem czasu... Co do i2c to najlepiej z wykrywaniem błędów magistrali.
    Niestety niemog obie poadzić pomimo iz znam mniejwiecej budowe avr i mniejwiecej wiem ile co teoretycznie powinno trwać ale po badaniu wychodzi ze trwa kilkakrotnie dłuzej...

    Pozdrawiam

    0
  • #4 14 Mar 2007 21:54
    rsikon
    Poziom 26  

    operacja udana :P

    Lekko dopieszcze kod i moze si podziele ;)

    0
  • #5 15 Mar 2007 17:28
    domelfm
    Poziom 16  

    Code:
    * Program demonstrujacy dzialanie termometru DS1820; 
    
    This program measure a temperature from DS1820 and shows it at LCD.
    Piny/Pins:
    PD1 - RS
    PD2 - E
    PD3 - D4
    PD4 - D5
    PD5 - D6
    PD6 - D7
    */

     
    #include <avr/io.h>
    #include <stdlib.h>
    #include <util/delay.h>

    #define _AVR_DELAY_H_ 1
    #define F_CPU 10000000UL

    #define DDR_DB4 DDRD
    #define PORT_DB4 PORTD
    #define DB4 PD3

    #define DDR_DB5 DDRD
    #define PORT_DB5 PORTD
    #define DB5 PD4

    #define DDR_DB6 DDRD
    #define PORT_DB6 PORTD
    #define DB6 PD5

    #define DDR_DB7 DDRD
    #define PORT_DB7 PORTD
    #define DB7 PD6


    #define DDR_RS DDRD
    #define PORT_RS PORTD
    #define RS PD1

    #define DDR_E DDRD
    #define PORT_E PORTD
    #define E PD2


    #define SET_B1 PORT_B1 |= _BV(B1)
    #define CLR_B1 PORT_B1 &= ~_BV(B1)

    #define SET_B2 PORT_B2 |= _BV(B2)
    #define CLR_B2 PORT_B2 &= ~_BV(B2)

    #define SET_B3 PORT_B3 |= _BV(B3)
    #define CLR_B3 PORT_B3 &= ~_BV(B3)

    #define SET_B4 PORT_B4 |= _BV(B4)
    #define CLR_B4 PORT_B4 &= ~_BV(B4)

    #define SET_DB4 PORT_DB4 |= _BV(DB4)
    #define CLR_DB4 PORT_DB4 &= ~_BV(DB4)

    #define SET_DB5 PORT_DB5 |= _BV(DB5)
    #define CLR_DB5 PORT_DB5 &= ~_BV(DB5)

    #define SET_DB6 PORT_DB6 |= _BV(DB6)
    #define CLR_DB6 PORT_DB6 &= ~_BV(DB6)

    #define SET_DB7 PORT_DB7 |= _BV(DB7)
    #define CLR_DB7 PORT_DB7 &= ~_BV(DB7)

    #define SET_E PORT_E |= _BV(E)
    #define CLR_E PORT_E &= ~_BV(E)

    #define SET_RS PORT_RS |= _BV(RS)
    #define CLR_RS PORT_RS &= ~_BV(RS)

    #define LCD_X 16
    #define LCD_Y 2

    unsigned char temperature;
    unsigned char temperatura=1;

    union {
    int tds;
    char nds[2];
    }ds;

    char buf[6];

    void out_nibble(char x)
    {
       CLR_DB4;
       CLR_DB5;
       CLR_DB6;
       CLR_DB7;
       if(x & _BV(0)) SET_DB4;
       if(x & _BV(1)) SET_DB5;
       if(x & _BV(2)) SET_DB6;
       if(x & _BV(3)) SET_DB7;
    }


    void write_to_lcd(char x)
    {
       SET_E;
       out_nibble(x >> 4);
       CLR_E;
       SET_E;
       out_nibble(x);




       CLR_E;
       _delay_ms(8);
       
       
    }

    void delay(int useconds)
    {
    int s;
    useconds = useconds;
    for (s=0; s<useconds;s++);
    }

    void write_command(char x)
    {
       CLR_RS;
       write_to_lcd(x);
    }

    void write_char(char x)
    {
       SET_RS;
       write_to_lcd(x);
    }

    void write_text(char * s)
    {
       while(*s)
       {
          write_char(*s);
          s++;
       }
    }

    void lcd_init(void)
    {
       DDR_DB4 |= _BV(DB4);
       DDR_DB5 |= _BV(DB5);
       DDR_DB6 |= _BV(DB6);
       DDR_DB7 |= _BV(DB7);
       DDR_E |= _BV(E);
       DDR_RS |= _BV(RS);

       
       _delay_ms(120);
       CLR_E;
       CLR_RS;
       char i;
       for(i = 0; i < 3; i++)
       {
          SET_E;
          out_nibble(0x03);
          CLR_E;
       _delay_ms(5);

       }
       SET_E;
       out_nibble(0x02);
       CLR_E;
       _delay_ms(8);
       write_command(0x28); // interfejs 4-bity, 2-linie, znak 5x7
       write_command(0x08); // wyłącz LCD, kursor i miganie
       write_command(0x01); // czyść LCD
       write_command(0x06); // bez przesuwania w prawo
       write_command(0x0C); // włącz LCD, bez kursora i mrugania
    }


    void LCD_xy(uint8_t x, uint8_t y)
    {
       switch(y)
       {
          case 1: y=0x40; break;
          case 2: y=0x14; break;
       }
       write_command(0x80+y+x);
    }

    void lcdxy(uint8_t x, uint8_t y)
    {
       switch(y)
       {
          case 1: y=0x40; break;
          case 2: y=0x14; break;
       }
       write_command(0x80+y+x);
    }
    void LCD_clr(void)
    {
       write_command(0x01);
       _delay_ms(8);
       
       LCD_xy(0,0);
    }
    //==========================================================================================//

    void dl(char x)
    {
    TCCR0=0x02;
    OCR0=x;
    while(1)
    {
    if(TCNT0>=OCR0)
    break;
    }
    TCCR0=0;
    TCNT0=0;
    }
    unsigned char ow_reset__(void) // reset lini one wire
    {
       unsigned char presence=1;
       DDRA |= _BV(0); //DQ = 0; //pull DQ line
       dl(240);
       dl(240);
       DDRA &= ~_BV(0); //DQ = 1; // allow line to //powrót lini 1w do trybu wejścia

       dl(60);// wait for presence pulse(pochodzący od DS-a) //czekamy na ustab. lini
       
       if(bit_is_clear(PINA,0)) presence=0; //odczytujemy co wystawił na linię DS
       dl(200);// wait for end
       dl(100); 
       return(presence); // presence signal
    } // 0=presence, 1 = no part


    unsigned char test(void) // test na oecnosc DALLASA
    {
    //LCD_xy(0,0); write_text("   TESTUJEMY   ");
    //_delay_ms(200);
    //_delay_ms(200);
    if (ow_reset__()==1)
    {
    LCD_xy(0,1); write_text("BRAK CZUJNIKA");
    _delay_ms(200);
    _delay_ms(200);

    }
    _delay_ms(200);
    _delay_ms(200);
    return 0;
    }


    //===========================================================================================//
    //===========================================================================================//



    unsigned char ow_reset(void) // reset lini one wire
    {
       unsigned char presence=1;
       DDRA |= _BV(0); //DQ = 0; //pull DQ line
       dl(240);
       dl(240);
       DDRA &= ~_BV(0); //DQ = 1; //powrót lini 1w do trybu wejścia
       dl(64);// wait for presence pulse(pochodzący od DS-a) //czekamy na ustab. lini
       if(bit_is_clear(PINA,0)) presence=0; //odczytujemy co wystawił na linię DS
       dl(255);// 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=0;
       DDRA |= _BV(0);    //DQ = 0; // pull DQ low to start timeslot
       dl(2);
       DDRA &= ~_BV(0);   //DQ = 1; // then return high
       dl(14); // delay 15us from start of timeslot
       if(bit_is_clear(PINA,0)) presence=0;
       if(bit_is_set(PINA,0)) 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.
    {
       DDRA |= _BV(0); //DQ = 0; // pull DQ low to start timeslot
       dl(2);
       if(bitval==1) DDRA &= ~_BV(0); //DQ =1; // return DQ high if write 1
       dl(104); // hold value for remainder of timeslot - delay 104us
       DDRA &= ~_BV(0);//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
          dl(120); // ??shifts it left wait for rest of timeslot 120us
       }
       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
       }
       dl(104);

    }

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



    void Read_Temperature(void)
    {
    //char tmp[10];
    char temp_lsbyte; //temp_msbyte;
    //int k;
    test();
    write_byte(0xCC); //Skip ROM
    write_byte(0x44); // Start Conversion
    dl(120);
    ow_reset();
    write_byte(0xCC); // Skip ROM
    write_byte(0xBE); // Read Scratch Pad

    ds.nds[0]=read_byte();
    ds.nds[1]=read_byte();

          LCD_xy(0,1);

             itoa(ds.tds/2,buf,10);//temper. całkowita
             write_text("Temp: ");
          write_text(buf);
          write_text(".\0");
             itoa(abs((ds.tds*10/16)%10),buf,10);   //części dziesiętne
             write_text(buf);
          write_text(" C");

    /*void Read_Temperature(void)
    {
    char get[10];
    char temp_lsb,temp_msb;
    int k;
    char temp_f,temp_c;
    ow_reset();
    write_byte(0xCC); //Skip ROM
    write_byte(0x44); // Start Conversion
    delay(5);
    ow_reset();
    write_byte(0xCC); // Skip ROM
    write_byte(0xBE); // Read Scratch Pad
    for (k=0;k<9;k++){get[k]=read_byte();}
    printf("\n ScratchPAD DATA = %X%X%X%X%X\n",get[8],get[7],get[6],get[5],get[4],get[3],get[2],get[1],get[0]);
    temp_msb = get[1]; // Sign byte + lsbit
    temp_lsb = get[0]; // Temp data plus lsb
    if (temp_msb <= 0x80){temp_lsb = (temp_lsb/2);} // shift to get whole degree
    temp_msb = temp_msb & 0x80; // mask all but the sign bit
    if (temp_msb >= 0x80) {temp_lsb = (~temp_lsb)+1;} // twos complement
    if (temp_msb >= 0x80) {temp_lsb = (temp_lsb/2);}// shift to get whole degree
    if (temp_msb >= 0x80) {temp_lsb = ((-1)*temp_lsb);} // add sign bit
    printf( "\nTempC= %d degrees C\n", (int)temp_lsb ); // print temp. C
    temp_c = temp_lsb; // ready for conversion to Fahrenheit
    temp_f = (((int)temp_c)* 9)/5 + 32;
    printf( "\nTempF= %d degrees F\n", (int)temp_f ); // print temp. F
    }*/
    /*
    lcdxy(0,0);


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

    read_byte();

    //printf("DAT=%X%X%X%X%X",tmp[8],tmp[7],tmp[6],tmp[5],tmp[4],tmp[3],tmp[2],tmp[1],tmp[0]);
    itoa(tmp[8],buf,10);//temper. całkowita
    LCD_xy(0,0); write_text(buf);

    itoa(tmp[7],buf,10);//temper. całkowita
    LCD_xy(2,0); write_text(buf);

    itoa(tmp[6],buf,10);//temper. całkowita
    LCD_xy(4,0); write_text(buf);

    itoa(tmp[5],buf,10);//temper. całkowita
    LCD_xy(6,0); write_text(buf);

    itoa(tmp[4],buf,10);//temper. całkowita
    LCD_xy(8,0); write_text(buf);

    itoa(tmp[3],buf,10);//temper. całkowita
    LCD_xy(10,0); write_text(buf);

    itoa(tmp[2],buf,10);//temper. całkowita
    LCD_xy(12,0); write_text(buf);

    itoa(tmp[1],buf,10);//temper. całkowita
    LCD_xy(14,0); write_text(buf);

    itoa(tmp[0],buf,10);//temper. całkowita
    LCD_xy(16,0); write_text(buf);
    */





    /*
    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
    */

    //printf( "TempC=%d C", (int)temp_lsbyte ); // print temp. C




    temperature=temp_lsbyte;

    }

     



    //===========================================================================================//
    //===========================================================================================//



    int main (void)


       dl(64);
       dl(25); 
       lcd_init();
       LCD_clr();
       DDRB=0x00;
       PORTB=0x00;


    write_byte(0xCC);

       while(1)
       {

    Read_Temperature();




       _delay_ms(155);
          _delay_ms(155);
          _delay_ms(155);
               _delay_ms(155);
       }     
    }


    Teraz tak wygląda kod...

    Niestety nadal nic....

    Jak widać delay zastąpiłem zliczaniem na liczniku.

    Układ taktuje 8Mhz

    0
  • #6 15 Mar 2007 18:52
    rsikon
    Poziom 26  

    "Kolo" ;)

    A może by i tak poinformować układ o prawdzie a nie kłamać??!!

    Piszesz, że taktujesz 8MHz a ja widze w kodzie na poczatku 1000000 a ne 8000000.

    A fuserbity zmieniłeś na 8MHz czy tylko wydaje Ci się że działa na 8MHz?

    Drąż temat... drąż... m się udało :)

    Przepraszam za zwrot Kolo ;) ale taki mam dziś dobry humor :)

    To kod termometru z mini bajera.... ;) Narazie nie mam czasu by doprwadzic go do ładu tak wec nie jest on zminimalizowany i pozbawiony zbednych smieci! Ale działa na 8MHz na Atmega16.


    Radzio

    0
  • #7 15 Mar 2007 20:14
    domelfm
    Poziom 16  

    sorki ale ta początkowa definicja 1000000 niema wpływu... :)
    Wszystko na licznikowym opuznieniu mam zrobione wiec jest sporo dokładniej niz na delayach...

    Pozdrawiam A te nieszcesne 1000000 zmieniłem na 8000000 i tez kicha.. :)

    0
  • #8 15 Mar 2007 20:21
    rsikon
    Poziom 26  

    W moim kofunkcja test...

    odpalic ja w petli... sprawdza czy dallas odpowiada... jesli nie odpowiada to moze cos nie tak podlaczone...

    jak odpowiada to tylko i wylacznie korekcja czasow zostaje...

    Najwyrazniej Twoje dokladniejsze odmierzanie jest cos nie tak albo zle wartosci odmierzasz.

    Tak przegladajac Twoj kod... pozamieniales funkcje dellay na swoje dl ale nie korygowales czasu! Ja powstawialem takie czy inne wartosci na podstawie symulacji a czy ty swoje sprawdzales ile tak naprawde odmierza w danym momencie??

    Moze pozniej sam to sprawdze bo zdaje mi sie ze wogolene zainteresowales sie protokolem 1wire dla tego czujnika i wogole nie wiesz ile gdzie powinno czasu byc odmierzone. Ale to bede wiedzial jak wrzuce pozniej Twoj kod na symulacje - narazie gdybam.

    Radzio

    I już po testach...

    Np., w dokumentacji DS18B20 mam coś takiego:
    "Odczyt wartości bitu przesyłanego przez układ podrzędny polega na generacji przez układ master impulsu o czasie trwania minimum 1 ms (zazwyczaj stosuje się impulsy 3 .. 5 ms), a następnie na zwolnieniu linii DQ i sprawdzeniu jej stanu logicznego przed upływem 15 ms od rozpoczęcia sekwencji odczytu ..."
    A symulator Twoje 15ms pokazuje mi jako 22 :)

    Niby nie wielka roznica ale... kto wie moze robi problem wlasne ona ;)
    Dopracuj czasy.

    Radzio

    0
  • #9 16 Mar 2007 01:48
    domelfm
    Poziom 16  

    hymm :) ale wałek...
    Musze popatrzeć na te czasy... ale odmierzanie na dl jest dość dokładne..
    o ile generator RC jest dokładny..

    Dodano po 45 [minuty]:

    Podzielisz się tym symulatorem avr ?
    Kulka mi cały czas wychodzą jakieś ciekawe .... wyniki....

    0
  • #10 16 Mar 2007 07:18
    rsikon
    Poziom 26  

    Symulator jest czescia AVR Studio.

    Radzio

    0
  • #11 16 Mar 2007 13:01
    domelfm
    Poziom 16  

    ... Wiem że jest...

    Tylko jak zmierzyć czas?

    Podrawiam.

    0
  • #12 16 Mar 2007 22:58
    domelfm
    Poziom 16  

    Code:

     
    #include <avr/io.h>
    #include <stdlib.h>
    #include <util/delay.h>

    #define F_CPU 80000000UL

    #define DQ 0

    #define SET_DQ DDRA &= ~_BV(DQ)
    #define CLR_DQ DDRA |= _BV(DQ)

    #define IN_DQ PINA & _BV(DQ)

    #define LCD  PORTA
    #define DLCD DDRA
    #define E  3
    #define RS  2
    //
    #define SET_E   LCD |= _BV(E)
    #define CLR_E   LCD &= ~_BV(E)
    //
    #define SET_RS  LCD |= _BV(RS)
    #define CLR_RS  LCD &= ~_BV(RS)

    char i,x,y;


    //==========================================LCD==================================================

    void dl(char x)
    {
    TCCR0=0x02;
    OCR0=x;
    while(1)
    {
    if(TCNT0>=OCR0)
    break;
    }
    TCCR0=0;
    TCNT0=0;

    }
    // funkcja opóźniająca o x*1ms
    void waitms(char x)
    {
    unsigned char a; // zmnienne licznikowe
    for( ; x > 0; --x) // ta pętla zostanie wykonana x-razy
    for(a = 5; a > 0; --a)
    dl(200);
    }

    // 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
    LCD = ((LCD & 0x0F) | (x & 0xF0)); // zapis pierwszej połówki bajtu
    CLR_E; // opadające zbocze na E -> zapis do wyświetlacza
    SET_E; // ustaw na E stan wysoki
    LCD = ((LCD & 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
    char i; // zmianna licznikowa
    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
      {
      SET_E; // E = 1
      LCD &= 0x3F; //
      CLR_E; // E = 0
      waitms(5); // czekaj 5ms
      }
    SET_E; // E = 1
    LCD &= 0x2E; //
    CLR_E; // E = 0
    waitms(1); // czekaj 1ms
    write_command(0x28); // interfejs 4-bity, 2-linie, znak 5x7
    write_command(0x08); // wyłącz LCD, kursor i miganie
    write_command(0x01); // czyść LCD
    write_command(0x06); // bez przesuwania w prawo
    write_command(0x0C); // włącz LCD, bez kursora i mrugania
    }


    void LCD_xy(char x, char y)
    {
       switch(y)
       {
          case 1: y=0x40; break;
          case 2: y=0x14; break;
       }
       write_command(0x80+y+x);
    }


    void LCD_clr(void)
    {
       write_command(0x01);
       waitms(1);
       
       LCD_xy(0,0);
    }
    //==========================================================================================//


    //---------------------------1-wire------------------------------


    ////////////////////////////////////////////////////////////////////////////////////
    unsigned char ow_reset__(void) // reset lini one wire
    {
       unsigned char presence=1;
       CLR_DQ; //DQ = 0; //pull DQ line
     
     dl(250);
     dl(200);//   450 us
     
       SET_DQ; //DQ = 1; // allow line to //powrót lini 1w do trybu wejścia

     dl(80);       //    31,88 us   wait for presence pulse(pochodzący od DS-a) //czekamy na ustab. lini
       
       if(IN_DQ) presence=1;
       else presence=0; //odczytujemy co wystawił na linię DS

      dl(200);
      dl(200);
       if(IN_DQ) presence=0;
       else presence=1;
       return(presence); // presence signal
    } // 0=presence, 1 = no part


    void test(void) // test na oecnosc DALLASA
    {
    LCD_xy(0,0); write_text("   TESTUJEMY   ");
    _delay_ms(200);
    _delay_ms(200);
    if (ow_reset__()==1)
    {
    LCD_xy(0,1); write_text("BRAK CZUJNKA");

    for(x=0;x<6;x++)
    _delay_ms(200);

    } else
    {
    LCD_xy(0,1); write_text("CZUJNIK OK!");

    for(x=0;x<6;x++)
    _delay_ms(200);
             
    }
    for(x=0;x<10;x++)
    _delay_ms(200);
                LCD_clr();
             
    }


    //===========================================================================================//
    //===========================================================================================//




     
     // 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=0;
       CLR_DQ;    //DQ = 0; // pull DQ low to start timeslot
       for(x=0;x<1;x++);
       asm ("nop");
       
       SET_DQ;   //DQ = 1; // then return high
       dl(5);; // delay 15us from start of timeslot
       
       if(IN_DQ) presence=1;
       else presence=0;
       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.
    {
       CLR_DQ;    //DQ = 0; // pull DQ low to start timeslot
       for(x=0;x<1;x++);
       asm ("nop"); 
       if(bitval==1)
       SET_DQ; //DQ =1; // return DQ high if write 1
       dl(60); // hold value for remainder of timeslot - delay 104us
       SET_DQ;//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
          dl(75);    // ??shifts it left wait for rest of timeslot 120us
       }
       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
       }
    dl(50);

    }
     



    //////////////////////////////////////////////////////////////////////////////////

    void Read_Temperature(void)
    {
    char tmp[10];
    char temp1, temp2;
    unsigned short int t;
    if (ow_reset__()==1)
    test();
    write_byte(0xCC); //Skip ROM
    write_byte(0x44); // Start Conversion
      _delay_ms(1000);
      _delay_ms(1000);
      _delay_ms(1000);
    ow_reset__();
    write_byte(0xCC); // Skip ROM
    write_byte(0xBE); // Read Scratch Pad



    temp1=read_byte();
    temp2=read_byte();

    ow_reset__();

    t = abs(((temp2 << 8) | temp1) * 10 / 16) ; //+ ((temp2 & 0x80) ? 0x00 : 600)

    dtostrf((float)t/10,5,1,tmp);
    LCD_xy(1,0);
    write_text(tmp);

    }
     



    //===========================================================================================//
    //===========================================================================================//



    int main (void)

    {

    // konfiguracja portów we/wy
    DLCD = 0xFC;
     LCD = 0xFC;
    DDRD=0xFC;
    PORTD=0xFC; 
       lcd_init();
       LCD_clr();
       //DDRB=0x00;
       //PORTB=0x00;


    //write_byte(0xCC);
    test();


       while(1)
       {
       
    Read_Temperature();
    for(i=0;i<30;i++){         //Tworzy opóźnienie do odświeżania temp
          _delay_loop_2(65535);

       }
     
        }
       
    }   
     


    Wydaje mi się że kod jest ok, ale jest jeden problem temp odczytana, cały czas ma wartość 85.2 st i wogle się nie zmienia niewiem dlaczego.
    Ta temperatura to jest temp która jest na starcie wpisana do ds po resecie zasilania (wyczytałem to w nocie katalogowej ds-a).

    0
  • #13 17 Mar 2007 17:39
    rsikon
    Poziom 26  

    Owszem pierwszy pomir taki mi pokazuje... ale kolejny juz jest ok.


    Radzio

    0
  • #14 17 Mar 2007 18:19
    domelfm
    Poziom 16  

    Niestety chyba mój czujnik jest do d...
    Albo ktoś może dojrzy ten maluśki błąd...
    JA niestety nie moge dojrzeć...

    Pozdrawiam.

    P.S

    Taka dobra rada co do tych czasów to jak macie jakąś funkcje podobną do mojego testu. To musicie tak dobierać czasy żeby czujnik cały czas był wykrywany(nagrzewajcie go zapalniczka wtedy mu się rozjeżdżają czasy).

    0
  • #15 18 Mar 2007 14:27
    szakamason
    Poziom 13  

    wreszcie odpaliłem mojego ds, w symulatorku działał zawsze ok, a w realu nie, przypomniałem sobie że w książce "uK AVR w praktyce" był kod źródłowy dla pastylki dallasa, i było to właśnie na 8MHz, tak więc skopiowałem bezczelnie funkcję opóźnienia w [us], wkleiłem do swojego programu i zaczęło działać, wyświetla cały zakres temperatur od -55 do 128oC. Wniosek, symulacja ds18"x"20 w proteusie przebiegała poprawnie dla teoretycznych-idealnych czasów ds'a, czasy te mierzone na wirtualnym analizatorze stanów logicznych były takie,jakie powinny wynikać z zastosowanej funkcji opóźnienia dla uK. W rzeczywistości jednak czasy odpowiedzi ds'a widocznie różniły się nieznacznie od katalogowych na tyle, by uniemożliwić poprawny odczyt z ds'a.

    0
  • #16 18 Mar 2007 16:13
    domelfm
    Poziom 16  

    Powiedz w jakim symulatorku odpaliłes tego dsa ?
    Jezeli mozesz to podziel się tym odkryciem.. :)

    Dodano po 11 [minuty]:

    HYmm własnie sprawdziłem... Ds nierozumie wysyłanych do niego komend..
    JEDYNIE RESET ROZUMIE...

    Czyli musze pokombinować.. Ale niewiem dlaczego tak jest..

    0
  • #17 18 Mar 2007 17:15
    rsikon
    Poziom 26  

    Proste :)

    czasy w wysyłaniu / odbieraniu bitów bajtów.

    Tam sa male i male tolerancje panuja.

    Radzio

    0
  • #18 18 Mar 2007 20:16
    domelfm
    Poziom 16  

    Kulka na symulatorku wyglądają na dobre.. :)
    a juz z nimi i tak trochę kombinowałem i nic..

    0
  • #19 18 Mar 2007 20:58
    Balu
    Poziom 38  

    Nagrzewanie czujnika zapalniczką to zdecydowanie kiepski pomysł.
    DS prawdopodobnie nie przeżyje "dłuższego" "rozjeżdżania czasów".

    0
  • #20 20 Mar 2007 23:37
    domelfm
    Poziom 16  

    Hymm.
    Czasy były dobre..
    Wymieniłem czujniki i działa wszystko jak nalezy.
    Kupiłem 2 nowe ale jeden znowu uwaliłem przez złe podłączenie polaryzacji i znowu wyswietla tylko 85st.

    Powiedzcie czy to jest mozliwe zeby przez sec spalić tego dallasa ?
    Zaledwie tylko dotknąłem i juz było po nim.
    Moze trafiłem na jakies trefne ?

    0
  • #21 21 Mar 2007 10:21
    Balu
    Poziom 38  

    Ja moje ds'y zawsze podłączałem na chybił trafił i żadnego nie spaliłem a przewaliło się przez moje łapy z 200 sztuk...

    0
  • #22 21 Mar 2007 12:18
    domelfm
    Poziom 16  

    A jak podłączasz ?
    Do zasilania na stałe czy zasilanie pasorzytnicze.... ?
    Tzn zasilanie na stała czty zasilanie z lini sygnalowej ?

    Pozdrawiam

    Ja zasilanie podłączam na stałem i zasilam z 5 v .

    0
  • #23 21 Mar 2007 21:54
    Balu
    Poziom 38  

    No to pewnie dla tego:)
    Ja zawsze na pasożyta;)

    0
  • #24 21 Mar 2007 23:21
    domelfm
    Poziom 16  

    Jak podłączasz na pasożyta... ?
    Mozesz schemacik narysować ?
    Głównie mam na myśli rozwiązanie zasilania w trakcie przeliczania...
    Pisze w specyfikacji, że nalezy na ten czas włączać zasilanie przez tranzystorek...

    Pozdrawiam...

    0
  • #25 21 Mar 2007 23:37
    smelektroda
    Poziom 12  

    Witam
    Gdzieś czytałem, że zasilanie poprzez linie stosuję się do pracy z układami, które charakteryzuja się małym poborem prądu.

    Natomiast, gdy chcemy mieć chwilowy dostęp do pełnego napięcia zasilania, podobno można zastosować taki układ z tranzystorem jak w załączniku.

    0
  • #26 21 Mar 2007 23:50
    domelfm
    Poziom 16  

    Też spotkałem się z tym układem....
    Tylko jak ma się to w praktyce.. :)
    Czekam na odpowiedz od praktyków..

    0
  • #27 21 Mar 2007 23:59
    smelektroda
    Poziom 12  

    Tez jestem ciekaw jak ma sie to w praktyce.
    A ja mam takie pytanko, bo się męcze troche z ds18b20:
    jeżeli w kodzie w funkcji ow_reset:

    unsigned char ow_reset__(void) // reset lini one wire
    {
    unsigned char presence=1;
    DDRA |= _BV(0); //DQ = 0; //pull DQ line
    dl(240);
    dl(240);
    DDRA &= ~_BV(0); //DQ = 1; // allow line to //powrót lini 1w do trybu wejścia

    dl(60);// wait for presence pulse(pochodzący od DS-a) //czekamy na ustab. lini

    if(bit_is_clear(PINA,0)) presence=0; //odczytujemy co wystawił na linię DS
    dl(200);// wait for end
    dl(100);
    return(presence); // presence signal
    } // 0=presence, 1 = no part

    mam źle dobrane czasy opóźnienia to wtedy presenence będzie 1 czyli no part, tak? Bo cały czas na lcd wyświetla mi się "cisza" (czyli nie ma czujnika) lub temp 0.0. Bo dobrze podłączam czujnik, ale cały czas nie wykrywa mi go. A czytając inne posty mimo złych czasów czasami wykrywa czujnik i wyswietla sie np. temp. 80 iles tam stopni C.

    Pozdrawiam

    0
  • #28 22 Mar 2007 00:43
    domelfm
    Poziom 16  

    Podrzucam programik po modyfikacjach.
    Działa dobrze.
    Jedyna jego wada że po kompilacji waży jakies 4,5 kb A to dość duzo tym bardziej ze słyszałem iż ludzie mieszczą się w 2- 2,5 kb.
    Przy okazji jeżeli ktoś miałby ochote podpowiedzieć mi jak zoptymalizować kod bede wdzieczny.

    Teraz odpowiedz na problem..
    Ta procedurę wykrywa tylko obecność ds. I czasy w niej sa poprawne.
    Odczyt ds zalezy od procedury odczytującej (nic nowego).
    A to co odczytamy zalezy od wczesniej wysłanych komend i sygnałów reset . Zobacz procedurę odczytującą ds. Jezeli mamy poprawną procedurę odczytu to na pewno odczytamy jakąś temp. 0 albo 85 zaleznie od wysyłanych sygnałów reset. A żeby odczytać włsciwą temperaturę ds musi mieć czas na przeliczenie jej oraz musi rozumieć wysyłane komendy do niego.

    0
  • #29 22 Mar 2007 09:41
    Balu
    Poziom 38  

    Szczerze mówiąc, to nie używam żadnego tranzystora:)
    do 100m działało bez problemu:)
    Po prostu zwierasz dwie zewnętrzne nóżki:)
    Jedyny wymóg to minimum 800ms przed konwersją linii w stanie wysokim (jakiś silny pull-up). No i afair wtedy nie masz max rozdzielczości... Co w wypadku tych czujek i tak jest zbyteczne bo one dość "interesująco" działają:P
    (dwie potrafią mieć rozrzut +-3*C)

    0
  • #30 06 Lip 2007 15:15
    CBR-MAR
    Poziom 9  

    witam
    Zarzucilem kod do DS'a od uzytkownika domelfm do AVRStudio 4.12 wersja beta + WINAVR 2005-11-i niestety wyskakuje mi błąd:(

    AllocationBase 0x0, BaseAddress 0x71590000, RegionSize 0x170000, State 0x10000
    C:\WinAVR\utils\bin\sh.exe: *** Couldn't reserve space for cygwin's heap, Win32 error 487
    avr-gcc.exe -mmcu=atmega32 -Wall -gdwarf-2 -O0 -MD -MP -MT Mtemp.o -MF dep/Mtemp.o.d -c ../Mtemp.c
    ../Mtemp.c:402: fatal error: opening dependency file dep/Mtemp.o.d: No such file or directory
    compilation terminated.
    make: *** [Mtemp.o] Error 1
    Build failed with 1 errors and 0 warnings...


    Moze mi ktos podpowie co z tym zrobic???
    Bardzo prosze o pomoc...

    0
  Szukaj w 5mln produktów