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

ATmega2560 [C] + DS18B20 i wciaz temperatura +127C lub +85C

MadArtSoft 29 Paź 2009 10:21 7990 33
REKLAMA
  • #1 7188645
    MadArtSoft
    Poziom 10  
    Witam,

    Przegladalem dziesiatki watkow o DS18B20 i niestety nie wyjasnilo to mojego problemu nad ktorym siedze juz chyba tydzien.

    Uzywam ATmega2560, DS18B20 i plyte startowa STK600.
    Zasilanie plyty z portu USB komputera. Napiecie zasilania 5V, podciagniety rezystor do DS18B20 4K7 (testowalem na 2K2, 3K3 rowniez) i problem ten sam wciaz temperatura 127 lub 85 stopni. Sprawdzalem na dwoch rodzajach oprogramowania i to samo. Zaznaczam ze czasami wczesniej calosc ruszyla i wskazywalo temperature poprawnie. Wiec wykluczam timingi. Uzywana rowniez biblioteka rklibavr. Po restarcie komputera 2 razy na 50 dobrze dzialalo. Nie zmienialem nic w programie ani w ustawieniach zegara. Oscylator jest zewnetrzny z STK600 4MHZ (sprawdzalem rowniez 8 i 16MHZ). Czujnik oddalony od portu zaledwie 7cm. Calosc sprawdzana na dwoch DS18B20. Taki sam efekt.

    Z gory dziekuje za wszelka pomoc. Chyba polegne na tych nieszczesnych czujnikach.

    Dodam ze podlaczam DSa 3-zyly z podciagnietym DQ.
  • REKLAMA
  • #2 7188998
    Konto nie istnieje
    Poziom 1  
  • #3 7189121
    mirekk36
    Poziom 42  
    Czujniki DS - Dallasa są bardzo przyjemne i łatwo się z nimi pracuje ale....

    ..... ale najczęściej można polec w tym temacie tylko wtedy gdy się stosuje jakieś gotowce nie do końca sprawdzone z netu - zamiast samemu w końcu zabrać się od samuśkiego początku za rozpoznanie tematu obsługi 1wire.

    bibliteki rklibavr w większości działają dobrze z różnymi peryferiami ale niestety zawierają także wiele błędów, które ludzie później powielają w swoich projektach - stąd takie efekty. Uważam jednak że te biblioteki jak i wiele innych w necie są bardzo dobrą podstawą do tego aby samemu na ich podstawie szybko pisać po woli własne procedury (biblioteki) do obsługi różnych rzeczy - wtedy zawsze będzie ci działać - tylko wiadomo - trzeba co nieco posiedzieć nad rozgryzieniem danego tematu. Jednak gdy to się już uda - to gwarantuję, że będziesz bardzo zadowolony - bo okaże się to w miarę proste a nie tak jak na początku - gdy podchodzi się do czegoś nowego jak do jeża i liczy tylko na to, że aaaa - złapię jakąś bibliotekę z neciku, coś tam przerobię i będzie śmigać

    tak jak kolega wyżej, ja też twierdzę, że masz właśnie problem z timingami i to wcale nic nie oznacza, że to już działało a teraz nie działa - takie właśnie można mieć problemy gdy timigi na 1wire są skopane

    druga sprawa - skoro pokazuje ci się najczęściej 85st C - to oznacza tylko, że albo w ogóle nie następuje odczyt (timingi) - bo same jedynki wpadają do procedury i wtedy masz temp max 127 - albo gdy jest 85st to znaczy, że udało się odczytać - tyle że wcześniej układ nie dostał nigdy prawidłowego polecenia dokonania konwersji temperatury. W nocie PDF jasno o tym pisze, że po resecie w układzie siedzi sobie wartość 85st C. A dlaczego nie dostał prawidłowego polecenia konwersji? - no bo o ile je masz? a chyba masz skoro kiedyś działało - to teraz to polecenie nie działa ze względu na timingi - i kółko się zamyka
  • #4 7189216
    Konto nie istnieje
    Poziom 1  
  • #5 7189404
    MadArtSoft
    Poziom 10  
    Witam,

    Ponizej umiescilem kod z ktorego korzystam. Odlaczylem LCD i sprawdzam tylko dwa pierwsze bajty. Zezygnowalem z innych bibliotek.

    
    #include <avr/io.h>
    #include <util/delay.h>
    //#include <avr/delay.h>
    #include <avr/signal.h>
    #include <avr/interrupt.h> 
    
    #define WE 0
    #define PORT_1wire PINC
    #define SET_1wire DDRC&=~_BV(WE)
    #define CLEAR_1wire DDRC |=_BV(WE)
    
    #define F_CPU 4000000UL
    
    char buf[8];
    
    unsigned char RESET_PULSE(void)
    {
    unsigned char PRESENCE;
    
    CLEAR_1wire;
    PORTC = 0x00;
    _delay_us(490);//490
    cli();
    SET_1wire;
    
    _delay_us(30);//30
    
    if (bit_is_clear(PORT_1wire, WE))
    {
    	PRESENCE=1;
    } 
    else 
    {
    	PRESENCE=0;
    }
    //sei();
    _delay_us(470);//470
    //loop_until_bit_is_set(PINA,0);
    if (bit_is_set(PORT_1wire, WE))
    {
    	PRESENCE=1;
    } 
    else 
    {
    	PRESENCE=0;
    }
    
    return (PRESENCE);
    } 
    
    void send(char bit)
    {
    	CLEAR_1wire;
    	PORTC = 0x00;
    	_delay_us(1);//5
        if(bit==1)
    	{
        	SET_1wire;
    	}
        
    	_delay_us(80);//80
        SET_1wire;
    }
    
    unsigned char read(void)
    {
       unsigned char PRESENCE=0;
       
       CLEAR_1wire;
       PORTC = 0x00;
       _delay_us(2);//2
       SET_1wire;
       _delay_us(14);//15
       
       if(bit_is_set(PORT_1wire, WE))
       	 PRESENCE=1;
       else
       {
         PRESENCE=0;
       }
    	//_delay_us(45);	
    
       return (PRESENCE);
    }
    
    void send_byte(char wartosc)
    {
       unsigned char i;
       unsigned char pom = 0;
       for (i=0; i<8; i++)
       {
       pom=wartosc>>i;
       pom&=0x01;
       send(pom);
       }
    _delay_us(100);//100
    }
    
    unsigned char read_byte(void)
    {
       unsigned char i;
       unsigned char wartosc=0;
    
       for (i=0; i<8; i++)
       {
    		if(read() == 1)
       			wartosc|=0x01<<i;
    
    		_delay_us(15);//15
       }
    	return(wartosc);
    } 
    
    void main(void)
    {
    	DDRB = 0xff;
    
    	unsigned char sprawdz;
    	unsigned char temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0, temp5 = 0;
    	unsigned char temp6 = 0, temp7 = 0, temp8 = 0, temp9 = 0;
    
    	//DDRA = 0;
    	//while(1){
    	//	PORTB = PINC;
    	//};
    
    	while(1){
    		
    		sprawdz = RESET_PULSE();
    
    		if(sprawdz == 1)
    		{	
                send_byte(0xCC);
                send_byte(0x44);
                _delay_us(800);//750
    
    			//PORTB = 1;
    			//while(read() == 0);
    			//loop_until_bit_is_set(PINA,0);
          
                sprawdz=RESET_PULSE();
    
                send_byte(0xCC);
                send_byte(0xBE);
    
                temp1=read_byte();
                temp2=read_byte();
                temp3=read_byte();
                temp4=read_byte();
                temp5=read_byte();
                temp6=read_byte();
                temp7=read_byte();
                temp8=read_byte();
    			temp9=read_byte();
    			   
                sprawdz=RESET_PULSE();
    
    			float temp = 0;
    			//temp = (float)(temp1+(temp2*256))/16;
    
    			//temp = (temp2<<8 | temp1) * 10 / 16;
    			
    			PORTB = temp1;	// Tutaj chce tylko odczytac wartosc LSB
    			_delay_ms(1000);
    			//PORTB = 32;
    			//_delay_ms(1000);
    			PORTB = temp2;	// Tutaj MSB
    			//_delay_ms(500);
    			//PORTB = temp2;
    			_delay_ms(2000);
    		}
    		else
    		{
    			PORTB = 3;
    			_delay_us(500); // Brak czujnika
    		}
    	}
    
    }
    


    Co do poprzedniej mojej wiadomosci to 127 = LSB 11111111 i MSB = 00000111.
  • REKLAMA
  • #6 7189596
    Konto nie istnieje
    Poziom 1  
  • #7 7189639
    MadArtSoft
    Poziom 10  
    Faktycznie nie jest to potrzebne. Po usunieciu podwojnego sprawdzania presence. Problem nie zostal rozwiazany. Dalej mam to samo. Czy moze to byc objaw uszkodzonego czujnika?

    Siedze juz tyle nad tym ze pomyslow mi brak i nie wiem co z tym dalej robic.
  • #8 7189684
    Konto nie istnieje
    Poziom 1  
  • #9 7191104
    MadArtSoft
    Poziom 10  
    Niestety powyzszy kod nie dziala. pierwsze dwa bajty zawieraja 0. Czujnik jest wykrywany.
  • #10 7191221
    Konto nie istnieje
    Poziom 1  
  • #11 7192159
    MadArtSoft
    Poziom 10  
    Zmienilem tak jak pisales ale zadnych rezultatow. Dodatkowo teraz nie wykrywa mi czujnika a dokladniej 2-ch czujnikow.

    Czy mozna jakos zblokowac DS-a ? Juz mi rozne pomysly przychodza. Czym wiecej modyfikuje czasy i rezystory tym gorsze wyniki. Czasow nie dobieram przypadkowo. Biore za przyklad oto ten opis: Opis
  • REKLAMA
  • #13 7192793
    MadArtSoft
    Poziom 10  
    Dziekuje za link. Dziala jak w pozostalych przypadkach. Tzn nie dziala.

    Zaglebilem sie troche w temacie i rozpoczalem sprawdzanie co faktycznie wychodzi z portu i co przychodzi. Moze to byc trudne poniewaz nie dysponuje oscyloskopem. Przychodzi mi do glowy mysl ze czujniki moga byc uszkodzone ale z drugiej strony dwa naraz i to w taki sam sposob sie zachowuja to troche malo prawdopodobne.

    Obecnie wskazania mam: LSB i MSB 11111111 11111111 brak reakcji na zmiany temperatury.
  • #14 7193344
    lastsith
    Poziom 10  
    Mam ten sam problem, tylko że piszę w assemblerze.
    Dzisiaj będe miec oscyloskop więc może rozwiąże ten nasz wspólny problem.
  • #15 7193399
    MadArtSoft
    Poziom 10  
    A wiec nie jest to wylacznie u mnie ten problem. Dzis posiedze nad tym i zdam relacje czy do czegos udalo mi sie dojsc. Podziel sie swoimi doswiadczeniami z oscyloskopem.
  • Pomocny post
    #16 7193581
    mirekk36
    Poziom 42  
    Panowie zamiast brać oscyloskop w rękę żeby sprawdzić czy czujniki na pewno działają - to weźcie sobie na chwilę Bascoma - napiszcie 2-3 linijki kodu i od razu sprawdzicie, że wam DS'y działają. Bascom ma gotowe i dobre procedury - więc sprawdzenie za jego pomocą czujników to pikuś nawet dla kogoś kto nigdy dotąd nie używał Bascoma. Jednak dla ludzi, którzy piszą w C czy w Asm - władają oscyloskopem itp - nie będzie problemem zajrzeć do helpa i zobaczyć jak napisać 2-3 linijki takiego kodu do sprawdzenia samych DS'ów

    a później szukajcie winy w waszym kodzie w C lub asm - bo na pewno tam jest pies pogrzebany (sprawdźcie jeszcze ustawienia fusów)
  • REKLAMA
  • #17 7195106
    MadArtSoft
    Poziom 10  
    Zrobilem tak jak kolega wyzej radzil, tzn. uruchomilem uklad uzywajac Bascom-a. Dziala! A wiec problem w C to timingi. Dzieki za pomoc przynajmniej wiem ze czujnik jest dobry.

    Jednak dalej pozostaje kwestia wykonania tego w C!
  • #18 7195467
    mirekk36
    Poziom 42  
    MadArtSoft --> najważniejsze to tak jak widzisz - umieć sobie radzić podążając jakimiś małymi krokami. Jednym z nich było to sprawdzenie z Bascomem ;)

    teraz ja na twoim miejscu - zabrałbym się po pierwsze za upewnienie się czy na 1000000% masz poprawnie ustawione fusebity (chodzi o częstotliwość taktowania procka - i czy takie masz ustawienie w projekcie programu)

    po drugie - pierwszy krok jaki bym starał się sprawdzić - to napisanie jakiejś procedury na sprawdzanie PRESENCE - czyli czy czujnik reaguje na RESET programowy 1wire. Jeśli tak to coś tam wyświetla się na LCD czy jakoś inaczej

    gdy już dojdziesz z tym do porządku to wtedy powinno pójść z górki - tzn proste procedury na odczyt i zapis bajtu 1wire

    a później to już wysyłanie po kolei komend i sprawdzanie odpowiedzi.

    Każdy z kroków da się ładnie po kolei przetestować nawet bez używania debugera itp
  • #19 7196957
    Konto nie istnieje
    Poziom 1  
  • #20 7197068
    MadArtSoft
    Poziom 10  
    Mam rozumiec tak ze jesli uklad Master nie nadaje to powinnienem ustawic np. DDRC = 0xff i PORTC = 0xff ??
  • #21 7197157
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #22 7197332
    mirekk36
    Poziom 42  
    ło matko ;) po opisie kolegi atom1477 i po tej informacji, że "Bascom coś kombinuje" można by uznać, że napisanie sotu do obsługi 1wire to rzecz prawie niemożliwa dla zwykłego śmiertelnika. Tymczasem to co robi Bascom to absoultnie nie żadna kombinacja tylko normalne zachowanie - ponieważ to podtrzymanie stanu wysokiego na pinie portu jest niejako przygotowaniem także do tego aby wraz z małym rezystorem podciągającym - można było podłączać czujniki w trybie parasite.

    Bo to w tym trybie kolego atom1477 jest istotne to, że układ pobiera w cudzysłowiu "sporo" prądu" gdy dokonuje konwersji temperatury. I nota PDF zaleca wtedy w ogóle tzw strong pull-up przez dodatkoy tranzystor. Ale praktyka pokazuje, że nawet bez tego tranzystora - tylko poprzez zasilanie czujnika z pinu portu wraz z małą wartością zewn rezystora podciągającego - można spokojnie zapewnić czujnikom potrzebną ilość prądu na magistrali.

    Gdy nie są podłączone w trybie Parasite(czyli dwu-przewodowo) - to wcale taka jak piszesz "kombinacja" nie jest potrzebna. Więc nie demonizujmy 1Wire.

    Kolega autor gdzieś cały czas popełnia ten sam błąd.

    Dodano po 10 [minuty]:

    przy okazji na dobry początek masz tu kilka podstawowych prostych funkcji, które używają zwykłych poleceń _delay_xxx z języka C. To na 100% działa tylko musisz mieć ustawione prawidłowo fusebity jeszcze raz podkreślam.

    
    
    #define WIRE_PORT PORTC
    #define WIRE_DIR DDRC
    #define WIRE_PIN PINC
    #define WIRE_CON 2
    
    
    //-------------------------------------------------------------------
    // 1-WIRE RESET
    //-------------------------------------------------------------------
    uint8_t OWTouchReset(void)
    {
       WIRE_DIR|=1<<WIRE_CON; // pin 1wire jako wyjscie
       WIRE_PORT&=~(1<<WIRE_CON); // pin 1wire -> 0
       _delay_us(650); // tx reset pulse
       WIRE_PORT|=1<<WIRE_CON; // pin 1wire -> 1 (koniec reset pulse)/pullup na wejscie
       WIRE_DIR&=~(1<<WIRE_CON); // pin 1wire jako wejscie
       _delay_us(70);
       if (bit_is_set(WIRE_PIN,WIRE_CON))
       {
          _delay_us(500); // tx reset pulse
          return 1; // zwraca jedynke jesli slave milczy
       }
       else
       {
          _delay_us(500); // tx reset pulse
          return 0; // zwraca zero jesli slave odpowiedzial
       }
    }
    //-------------------------------------------------------------------
    // 1-WIRE WRITE BYTE
    //-------------------------------------------------------------------
    void OWWriteByte (uint8_t data)
    {
       uint8_t i;
       WIRE_DIR|=1<<WIRE_CON; // pin 1wire jako wyjscie
       WIRE_PORT|=1<<WIRE_CON;   // pin 1wire -> 1
       for (i=0; i<8; i++)
       {
          if((data&0b00000001) == 1)
          {
             WIRE_PORT&=~(1<<WIRE_CON); // pin 1wire -> 0
             _delay_us(5);
             WIRE_PORT|=1<<WIRE_CON; // pin 1wire -> 1
             _delay_us(65);
          }
          else
          {
             WIRE_PORT&=~(1<<WIRE_CON); // pin 1wire -> 0
             _delay_us(70);
             WIRE_PORT|=1<<WIRE_CON; // pin 1wire -> 1
          }
          _delay_us(5);
          data>>=1;
       }
    }
    //-------------------------------------------------------------------
    // 1-WIRE READ BYTE
    //-------------------------------------------------------------------
    uint8_t OWReadByte (void)
    {
       uint8_t data=0;
       uint8_t i;
       for (i=0; i<8; i++)
       {
          data>>=1;
          WIRE_DIR|=1<<WIRE_CON; // pin 1wire jako wyjscie
          WIRE_PORT&=~(1<<WIRE_CON);   // pin 1wire -> 0
          _delay_us(1);
          WIRE_PORT|=1<<WIRE_CON; // pin 1wire -> 1 / pullup on
          _delay_us(13);
          WIRE_DIR&=~(1<<WIRE_CON); // pin 1wire jako wejscie
          if(bit_is_set(WIRE_PIN,WIRE_CON))
          {
             data|=0b10000000;
          }
          else
          {
             data&=0b01111111;
          }
          _delay_us(70);
       }
       return data;
    }
  • #23 7201330
    MadArtSoft
    Poziom 10  
    W ostatnim poscie kolega zwrocil mi uwage na pewna rzecz. Mianowicie w momencie zapisu bitow do DSa. Przelaczalem linie z wyjscia na wejscie co bylo niepotrzebne. Wystarczylo sterowac odpowiednio ustawiajac 0 lub 1 na magistrale ustawiona jako wyjsce i wyglada na to ze zaczelo dzialac.

    Dzieki za pomoc wszystkim ktorzy podsylali swoje pomysly. Mam nadzieje ze nie przestanie to dzialac ;)
  • #24 7224165
    lordadam
    Poziom 10  
    Mam do was pytanie . Może moja wiedza na ten temat nie jest dobra ale czemu jak podaje na wyjście mikrokontrolera do którego mam połączoną nóżkę DQ Dallasa to na tejże nóżce mam napięcie 4,23V ?? Dodam oczywiście, że Dallas jest zasilany zewnętrznie i między zasilaniem a DQ jest umieszczony rezystor 4,7k . Dzięki za odpowiedź.
  • #25 7224527
    mirekk36
    Poziom 42  
    lordadam napisał:
    Mam do was pytanie . Może moja wiedza na ten temat nie jest dobra ale czemu jak podaje na wyjście mikrokontrolera do którego mam połączoną nóżkę DQ Dallasa to na tejże nóżce mam napięcie 4,23V ?? Dodam oczywiście, że Dallas jest zasilany zewnętrznie i między zasilaniem a DQ jest umieszczony rezystor 4,7k . Dzięki za odpowiedź.


    coś za długie zdania budujesz i się gubisz ;)

    .... jak co podajesz na wyjście mikrokontrolera????
  • #26 7225235
    lordadam
    Poziom 10  
    np. Chcę zapisać do Ds18b20 "0" . Linię DQ czujnika mam podpiętą do pinu 0 PORTF atmegi. Gdy ustawiam ten port na wyjściowy o do dego portu wpisuje wartość "0" . Na nóżce DQ dallasa mam napięcie 4,23V a chyba tak nie powinno być.
  • #28 7226464
    lordadam
    Poziom 10  
    Przykładowo coś takiego. O ile dobrze myślę to na nóżce DQ dallasa powinno być 0 a tak nie jest . Dodam, że w trybie parasite power wszystko jest ok.


    
    #define F_CPU 16000000UL
    #include <avr\io.h>
    #include <util/delay.h>
    #include <stdlib.h>
    
    #include "lcd.h"
    
    
    #define WIRE_PORT PORTF
    #define WIRE_DIR DDRF
    #define WIRE_PIN PINF
    #define WIRE_CON 0 
    
    int main(void)
    {
    	LCD_init();
    	LCD_clear();
    	LCD_control(ON, BLINK, SHOW);
    	char tekst[128]="WYKRYTO";
    	char tekst2[128]="NIE WYKRYTO";
    	int presence=0;
    	WIRE_DIR|=1<<WIRE_CON; // pin 1wire jako wyjscie
    	for(;;)
    	{	
    
    		
                    WIRE_PORT&=~(1<<WIRE_CON); // pin 1wire -> 0
    	}	
    	return 0;
    }	
    
  • #29 7302426
    PiotrP70
    Poziom 10  
    Witam mam ten sam problem albo 127 albo 85, nadmienię iż program napisany w c jeden czujnik widzi i odczytuje (pomijana jest identyfikacja rom), natomiast po odłączeniu tego czujnika, podłączeniu innego (oczywiście zresetowany układ), juz wskazuje wartość np 127 a dla następnego (innego) np 85 (dla tego samego programu).
    Obecnie posiadam 4 czujniki z tego jeden sprzed 2 lat a trzy zakupione niedawno, ten sprzed 2 lat działa bez problemu, natomiast nowe nie. Wszystkie są podłączane jako 1-wire, zasilanie podciągnięte przez 4.7 przez nóżkę sygnałową i podłączony gnd, (+5 wolne nie podłączone).
    Wszystkie czujniki zostały sprawdzone w bascomie i wszystkie odczytały temperaturę,
    natomiast w c nie, wydłużenie czasu na konwersję nic nie pomogło.
    Czy przypadkiem nie jest coś zmienione w najnowszej wersji czujników??
  • #30 7491439
    czech_w
    Poziom 12  
    Podepnę się do tematu. U mnie wygląda to tak że mam podpięte 3 czujniki na różnych portach 2 działają ok 3 jak mu zmieniłem czasy pokazuje 85 st przedtem 127 natomiast jak go przytrzymam palcem pokazuje 127 st wygląda jak by padł bo na zmiane temp działa natomiast tylko progowo 85 lub 127 st więc pytanie czy mam rację z innym jeszcze nie sprawdzałem

    Dodano po 7 [minuty]:

    już wiem dlaczego pomyliłem piny i wlutowałem o 180 st na odwrót tzn + zamiast - a - zamiast + co spodowało chyba uszkodzenie czujnika z nowym działa poprawnie.

    Sprawdziłem po tej "pomyłce" DS się tak zachowuje tzn. mój czyli działa progowo tylko ten próg to ok 20 ÷ 25 °C
REKLAMA