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

atmega128 + ds18b20 zly odczyt temperatury

lordadam 14 Paź 2009 22:27 2884 15
REKLAMA
  • #1 7129722
    lordadam
    Poziom 10  
    Witam!

    Pierwsze co chciałbym powiedzieć to wiem, że informacji o tym czujniku jest pełno na forum, ale ja już stosowałem wiele sposobów i nic. Otóż mój problem jest taki, że czujnik cały czas podaje mi temperaturę -0.1 . Czujnik jest podłączony w trybie z zewnętrznym zasilaniem (trzy przewody) . Do szyny danych podciągnięty jest plus przez rezystor 4,7k . Szyna danych podłączona do PIND0 . Zegar 16MHz .

    Oto kod:

    
    #define F_CPU 16E6
    
    #include <avr\io.h>
    #include <util/delay.h>
    #include <stdlib.h>
    
    #include "lcd.h"
    
    #define WE 0
    #define PORT_1wire PIND
    #define SET_1wire DDRD&=~_BV(WE)
    #define	CLEAR_1wire DDRD|=_BV(WE)
    
    char buf[8];
    
    unsigned char RESET_PULSE(void)
    {
    	unsigned char PRESENCE;
    	
    	CLEAR_1wire;
    	_delay_us(500);
    	SET_1wire;
    	_delay_us(30);
    	if(bit_is_clear(PORT_1wire,WE)){PRESENCE=1;}else{PRESENCE=0;}
    	_delay_us(470);
    	if(bit_is_set(PORT_1wire,WE)){PRESENCE=1;}else{PRESENCE=0;}
    	return PRESENCE;
    }
    
    void send(char bit)
    {
    	CLEAR_1wire;
    	_delay_us(5);
    	if (bit==1)
    	{
    		SET_1wire;
    		_delay_us(80);
    		SET_1wire;
    	}
    }
    
    unsigned char read()
    {
    	unsigned char PRESENCE;
    	CLEAR_1wire;
    	_delay_us(2);
    	SET_1wire;
    	_delay_us(15);
    	if(bit_is_set(PORT_1wire,WE)){PRESENCE=1;}else{PRESENCE=0;}
    	return PRESENCE;
    }
    
    void send_byte(char wartosc)
    {
    	unsigned char i;
    	unsigned char pom;
    
    	for(i=0;i<8;i++)
    	{
    		pom = wartosc>>i;
    		pom &= 0x01;
    		send(pom);
    	}
    	_delay_us(100);
    }
    
    unsigned char read_byte()
    {
    	unsigned char i;
    	unsigned char wartosc=0;
    
    	for(i=0;i<8;i++)
    	{
    		if(read()) wartosc|=0x01<<i;
    		_delay_us(15);
    	}
    	return wartosc;
    }
    
    
    
    
    
    
    
    int main()
    {
    	static char tekst[128]="OK";
    	static char tekst2[128]="NO";
    	unsigned char sprawdz;
    	char temp1=0 , temp2=0; 
    
    
    			LCD_init();
        		LCD_control(ON, BLINK, SHOW);
    			
    
    	for(;;)
    	{
    		sprawdz=RESET_PULSE();
    		if(sprawdz==1)
    		{
    			send_byte(0xCC);
    			send_byte(0x44);
    			_delay_ms(800);
    			
    			sprawdz=RESET_PULSE();
    			send_byte(0xCC);
    			send_byte(0xBE); 
    
    			temp1=read_byte();
    			temp2=read_byte();
    
    			sprawdz=RESET_PULSE();
    
    			float temp=0;
    			temp=(float)(temp1+(temp2*256))/16;
    				
    			
    			dtostrf(temp,1,1,buf);
    
    			LCD_clear();
    			LCD_setpos(0);
    			LCD_putstring(buf);
    		}
    		else if (sprawdz==0)
    		{
    			LCD_clear();
    			LCD_setpos(0);
    			LCD_putstring(tekst2);
    		}
    	}
    	for(;;)
    	return 0;
    }
    
    


    Siedzę już nad tym dość długo i nie mogę nic wymyślić , może to jest jakiś głupi błąd którego nie mogę znaleźć. Dzięki za pomoc.
  • REKLAMA
  • REKLAMA
  • #3 7129987
    lordadam
    Poziom 10  
    Zmieniłem, niestety nie pomogło .
  • #4 7130077
    Konto nie istnieje
    Poziom 1  
  • #5 7130149
    lordadam
    Poziom 10  
    Może głupie pytanie ale jak go wyłączyć ??

    Zrobiłem coś takiego ale nie wiem czy o to chodzi:



    W każdym razie nie pomogło
  • REKLAMA
  • #6 7130179
    Konto nie istnieje
    Poziom 1  
  • #7 7130182
    lordadam
    Poziom 10  
    W fuse bits mam ustawione na
    Cytat:
    Ext. Crystal/Resonator High Freq.; Start-up time: 16K CK + 64 ms

    Więc chodzi na zewnętrznym kwarcu 16Mhz

    JTAG i tryb zgodności z 103 wyłączony.

    Nasuwa mi się już tylko myśl, że ds jest popsuty:(
  • #8 7130199
    Konto nie istnieje
    Poziom 1  
  • #9 7130211
    lordadam
    Poziom 10  
    Układ odpowiada na Reset Pulse więc jako tako jeszcze działa ale potem coś jest nie tak.
  • REKLAMA
  • #10 7130276
    zumek
    Poziom 39  
    lordadam napisał:
    ... ale potem coś jest nie tak.

    Zastanów się, co w tej funkcji jest ..."popsute" :-P
    
    void send(char bit)
    {
       CLEAR_1wire;
       _delay_us(5);
       if (bit==1)
       {
          SET_1wire;
          _delay_us(80);
          SET_1wire;
       }
    }
  • #11 7131314
    lordadam
    Poziom 10  
    Według mnie ta funkcja jest ok, ponieważ Wysłanie bitu polega na ustawieniu magistrali w stan niski, następnie jeśli po czasie min. 1μszostanie ona ustawiona w stan wysoki, równoznaczne jest to z wysłaniem jedynki. Jeśli z kolei po wyczyszczeniu magistrali nie nastąpi w określonym czasie podciągnięcie jej do jedynki to
    uznaje się to za wysłanie zera logicznego.

    Ale, żeby nie być zadufanym w swoim kodzie zastosowałem taki przykład z kodu zamieszczonego w jednym watku:

    
    void send(char bit)
    {
    	CLEAR_1wire;
    	_delay_us(15);
    	if (bit==0)
    	{
    		_delay_us(60);
    		SET_1wire;
    		_delay_us(2);
    	}
    
    	else
    	{
    		SET_1wire;
    		_delay_us(80);
    	}
    }
    


    Niestety czujnik nadal pokazuje -0.1
  • #12 7131514
    tmf
    VIP Zasłużony dla elektroda
    Masz skopane RESET_PULSE, zobacz koncowke i twoje badanie czy jest ok. Masz skopane send (to oryginalne), to powyzej tez - za dlugi jest impuls ujemny, masz skopane send_byte - zobacz jakie sa timingi pomiedzy bitami, a jakie ty masz. read_byte moze jest ok, ale tez nie jest idealne.
  • #13 7135100
    lordadam
    Poziom 10  
    Witam, zmieniłem trochę program oraz czujnik w tryb parasite power . Sytuacja trochę się poprawiła ale niewiele . Czujnik cały czas pokazuje temperaturę 128.0 stopni . Na początku jak dałem mu za mały czas po komendzie konwersji (0x44) to podawał 85.1 stopnia czyli jak to było gdzieś już powiedziane na forum to nie wyrabiał się z konwersją . Po zwiększeniu czasu pokazuje 128.0 . Oto program:

    
    
    # define F_CPU 1000000UL
    #include <avr\io.h>
    #include <util/delay.h>
    #include <stdlib.h>
    
    #include "lcd.h"
    
    
    #define WE 0
    #define PORT_1Wire PIND
    #define SET_1Wire DDRD&=~_BV(WE)
    #define CLEAR_1Wire DDRD|=_BV(WE)
    
    
    
    unsigned char RESET_PULSE(void)
    {
       unsigned char PRESENCE=0;
       int i;
       CLEAR_1Wire;
       _delay_us(480);
       SET_1Wire;
       _delay_us(15);
       for(i=0;i<55;i++)
       {
          if(bit_is_clear(PORT_1Wire,WE)) PRESENCE=1;
          _delay_us(1);
       }
       _delay_us(600);
       return PRESENCE;
    }
    
    
    void send(char bit)
    {
       CLEAR_1Wire;
       _delay_us(2);
       if(bit==1) SET_1Wire;
       _delay_us(80);
       SET_1Wire;
    
    }
    
    unsigned char read(void)
    {
       unsigned char i, PRESENCE=0;
       CLEAR_1Wire;
       _delay_us(6);
       SET_1Wire;
       _delay_us(7);
       for(i=0;i<50;i++)
       {
          if(bit_is_clear(PORT_1Wire,WE)) PRESENCE=1;
          _delay_us(1);
       }
       _delay_us(50);
       return(PRESENCE);
    }
    
    void send_byte(char wartosc)
    {
       int i;
       unsigned char pom;
       for(i=0;i<8;i++)
       {
          pom=wartosc>>i;
          pom&=0x01;
          send(pom);
       }
       _delay_us(20);
    }
    
    unsigned char read_byte(void)
    {
       uint8_t i;
       unsigned char wartosc=0;
       for(i=0;i<8;i++)
       {
          if(read()) wartosc|=0x01<<i;
       }
       return(wartosc);
    }
    
    float getTemp(void)
    {
    unsigned char PRESENCE;
    char temp1=0, temp2=0;
    PRESENCE=RESET_PULSE();
     if(PRESENCE==1)
     {
      send_byte(0xCC);
      send_byte(0x44);
      _delay_ms(800);
      PRESENCE=RESET_PULSE();
      send_byte(0xCC);
      send_byte(0xBE);
      temp1=read_byte();
      temp2=read_byte();
      PRESENCE=RESET_PULSE();
      float temp=0;
      temp=(float)(temp1+(temp2*256))/16*(-1);
      return temp;
     }
     else
     {
      return 0;
     }
    }
    
    
    int main()
    {
    	float temperatura;
    	char tekst[]="128";
    	char bufor[8];
    	LCD_init();
    	LCD_control(ON, BLINK, SHOW);
    
    	for(;;)
    	{
    		temperatura=getTemp();
    
    		dtostrf(temperatura,1,1,bufor);
    		LCD_clear();
    		LCD_setpos(0);
    		LCD_putstring(bufor);
    		_delay_ms(1000);
    	}
    }
    
    


    Dodam, że zmieniłem też zegar na 1Mhz wewnętrzny. Siedzę już nad tym kilka dni więc jeśli ktoś mógłby mi pomóc to będę bardzo wdzięczny.
  • #14 7135573
    tmf
    VIP Zasłużony dla elektroda
    Tym razem read jest zle napisane - zauwaz, ze petla + wczesniejsze opoznienia trwa co najmniej 63us, czyli czasami moze czytac 0 jako 1. Poza tym po co w petli to czytasz? Juz bym zrozumial gdybys zrobil jakies odszumianie, ale tak zwracasz ostatnia przeczytana wartosc. Odstepy pomiedzy bitami sa ciagle za krotkie - czemu nie probkujesz kiedy linia wroci do "1"? I najwazniejsze - zle wstawiasz bity w procedurze read_byte, ma byc >> a nie <<. Dla porownania rzuc okiem na moje dzialajace procedury:
    http://idom.svn.sourceforge.net/viewvc/idom/I2C/src/1wire.c?revision=63&view=markup
  • #15 7147859
    lordadam
    Poziom 10  
    Zmiany poczynione jednak efekt ciągle ten sam :(

    
    unsigned char RESET_PULSE(void)
    {
       unsigned char PRESENCE;
       
       CLEAR_1wire;
       _delay_us(500);
       SET_1wire;
       _delay_us(30);
       if(bit_is_clear(PORT_1wire,WE)){PRESENCE=1;}else{PRESENCE=0;}
       _delay_us(470);
       if(bit_is_set(PORT_1wire,WE)){PRESENCE=1;}else{PRESENCE=0;}
       return PRESENCE;
    }
    
    void send(char bit)
    {
       CLEAR_1wire;
       _delay_us(3);
       if (bit==1)SET_1wire;
          _delay_us(60);
          SET_1wire;
    }
    
    unsigned char read()
    {
       unsigned char PRESENCE;
       CLEAR_1wire;
       _delay_us(3);
       SET_1wire;
       _delay_us(15);
       if(bit_is_set(PORT_1wire,WE)){PRESENCE=1;}else{PRESENCE=0;}
       return PRESENCE;
    }
    
    void send_byte(char wartosc)
    {
       unsigned char i;
       unsigned char pom;
    
       for(i=0;i<8;i++)
       {
          pom = wartosc>>i;
          pom &= 0x01;
          send(pom);
    	  _delay_us(100);
       }
    
    }
    
    unsigned char read_byte()
    {
       unsigned char i;
       unsigned char wartosc=0;
    
       for(i=0;i<8;i++)
       {
       		wartosc>>=1;	
          if(read()) wartosc|=0x80;
          _delay_us(150);
       }
       return wartosc;
    }
    
    
    
    
    
    
    
    
    
    int main()
    {
       static char tekst[128]="OK";
       static char tekst2[128]="NO";
       unsigned char sprawdz;
       char temp1=0 , temp2=0;
    
    
             LCD_init();
              LCD_control(ON, BLINK, SHOW);
             
    
       for(;;)
       {
          sprawdz=RESET_PULSE();
          if(sprawdz==1)
          {
             send_byte(0xCC);
             send_byte(0x44);
             _delay_ms(1000);
             
             sprawdz=RESET_PULSE();
             send_byte(0xCC);
             send_byte(0xBE);
    
             temp1=read_byte();
             temp2=read_byte();
    
             sprawdz=RESET_PULSE();
    
             float temp=0;
             temp=(float)(temp1+(temp2*256))/16;
                
             
             dtostrf(temp,1,1,buf);
    
             LCD_clear();
             LCD_setpos(0);
             LCD_putstring(buf);
          }
          else if (sprawdz==0)
          {
             LCD_clear();
             LCD_setpos(0);
             LCD_putstring(tekst2);
          }
       }
       
       return 0;
    }
    
    
  • #16 7159266
    beznazwie
    Poziom 11  
    Oryginalny kod, który napisałeś - wbrew temu, co piszą niektórzy - działa, pomimo pozornie błędnych opóźnień (pomijając tą dziwną wartość F_CPU). Dziś właśnie użyłem identycznego kodu (czyżby z pewnego pdf'a? :) ) i udało mi się wreszcie uruchomić swój termostat cyfrowy.

    Nie widzę w Twoim kodzie konfiguracji pinów. Pin, pod który masz podłączoną linię danych, ustaw w DDRD jako wyjście ze stanem początkowym 0 (w PORTD).
REKLAMA