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

DS18B20 z ATMEGA8 i LCD - brak odczytu temperatury, czujnik nie odpowiada

czech_w 08 Kwi 2008 23:34 4849 17
  • #1 5009659
    czech_w
    Poziom 13  
    Posty: 80
    Pomógł: 1
    Ocena: 12
    Przepraszam o pytanie z cyklu 1000 i 1 opowieści ale kombinuje na wszystkie mi znane sposoby i sposoby z forum a nawet gotowca odpaliłem i też nie działa. Problem jak oszukam sprawdzanie DS to mam 0.0 jak nie oszukam to mam brak czujnika czyli mój DS nie odpowiada na reset czy jakoś tak (w innym kodzie zwracał mi 0.8). Posprawdzałem piny ścieżki i deklaracje i ok. Oto kod gotowca jak było WE 0 a jest 7 i pod 7 jest podpięty czujnik to jest ok (wiem że tak ale każdy się myli ;))


    
    #include <avr/io.h>
    #include <stdlib.h>
    #include "lcd.h"
    
    //makra
    
    #define WE 7
    #define PORT_1wire PIND
    #define SET_1wire DDRD&=~_BV(WE)
    #define CLEAR_1wire DDRD|=_BV(WE)
    
    char buf[8]; //zmienna do konwersji temperatury
    // reset magistarali
    
    unsigned char RESET_PULSE(void)
    {
    unsigned char PRESENCE;
    CLEAR_1wire;
    delayus(600);
    SET_1wire;
    delayus(50);
    if (bit_is_clear(PORT_1wire, WE)){PRESENCE=1;} else {PRESENCE=0;}
    delayus(470);
    if (bit_is_set(PORT_1wire, WE)){PRESENCE=1;} else {PRESENCE=0;}
    return (PRESENCE);
    }
    
    void send(char bit)
    {
    CLEAR_1wire;
    delayus(5);
    			if(bit==1)
    				SET_1wire;
    				delayus(80);
    				SET_1wire;
    }
    
    unsigned char read(void)
    {
    	unsigned char PRESENCE=0;
    	
    	CLEAR_1wire;
    	delayus(2);
    	SET_1wire;
    	delayus(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);
    	}
    delayus(100);
    }
    
    unsigned char read_byte(void)
    {
    	unsigned char i;
    	unsigned char wartosc=0;
    	
    	for (i=0; i<8; i++)
    	{
    	if(read()) wartosc|=0x01<<i;
    	delayus(15);
    	}
    return(wartosc);
    }
    
    
    int main(void)
    {
    unsigned char sprawdz;
    char temp1=0, temp2=0;
    
    LCD_init();
    LCD_clear();
    LCD_putstr_P(PSTR("1-wire"));
    LCD_xy(0,1);
    LCD_putstr_P(PSTR("DS18B20"));
    delayms(1000);
    LCD_clear();
    
    for(;;){
    		sprawdz=RESET_PULSE();
    			if (sprawdz==1)
    				{
    				send_byte(0xCC);
    				send_byte(0x44);
    				delayms(750);
    				
    				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_xy(0,0);
    				LCD_putstr(buf);
    				delayms(200);
    				}
    				else
    				{
    				LCD_xy(0,0);
    				LCD_putstr_P(PSTR("Brak czujnika"));
    				LCD_xy(0,1);
    				LCD_putstr_P(PSTR("DS18B20"));
    				}
    }
    }
    


    PS podpinałem już 3 DSy zasilanie z zewnątrz nie pasożyt (- DQ +)
    Proszę o pomoc
  • Pomocny post
    #2 5009689
    don diego
    Poziom 32  
    Posty: 1557
    Pomógł: 165
    Ocena: 63
    Masz podciąganie linii danych?
  • Pomocny post
    #3 5009857
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 241
    Ja puścił program w pętli (samo reset-response) i popatrzył oscyloskopem, w ostateczności zacznij od "spowolnienia" opóźnień do rzędu kilku s i sprawdź woltomierzem czy przebiegi się zgadzają.
  • #4 5009901
    lobmerd
    Poziom 12  
    Posty: 32
    Pomógł: 2
    Zadeklarowałeś częstotliwość zegara? Jeśli podczas kompilacji jest przyjmowana zła częstotliwość zegara to delay będzie źle działał. Tak samo może być jeśli użyłeś optymalizacji -O0.
  • #5 5016579
    czech_w
    Poziom 13  
    Posty: 80
    Pomógł: 1
    Ocena: 12
    Faktycznie nie miałem podciągania. Natomiast co do optymalizacji to jest ustawiona na
    # Poziom optymalizacji (0, 1, 2, 3, s)
    # (Uwaga: 3 nie zawsze jest najlepszym wyborem)
    OPT = s"

    Natomiast po podciągnięciu mam wynik -0.1 i jeszcze jedno program twierdzi że ma DS'a jak go niema .

    Coś w programie też skopałem albo ten delay nie działa poprawnie.
    Zaczyna sprawdzać.
  • Pomocny post
    #6 5020458
    ksarim
    Poziom 15  
    Posty: 168
    Pomógł: 17
    Ocena: 8
    Witam

    Nie widzę deklaracji funkcji: delayus() oraz delayms().
    W bibliotece delay.h funkcje te wyglądają tak: delay_us() i delay_ms().
    Tak naprawdę właśnie dobór opóźnień jest najistotniejszy przy komunikacji po 1-Wire. Wiem bo sam męczyłem się trochę z tym czujnikiem. Niestety funkcję dostępne standardowo w bibliotece delay.h ( delay_us() i delay_ms() ) faktycznie nie dają takich opóźnień jak wynikałoby to z deklaracji funkcji dlatego funkcję opóźniającą trzeba napisać samemu lub można wykorzystać inną funkcję dostępną w bibliotece delay.h umożliwiającą osiągnięcie dokładnych czasów opóźnień a mianowicie:

    _delay_loop_2(uint16_t __count)
    {
    __asm__ volatile (
    "1: sbiw %0,1" "\n\t"
    "brne 1b"
    : "=w" (__count)
    : "0" (__count)
    );
    }

    Taka funkcja opóźniająca daje Ci opóźnienie trwające 4*(parametr funkcji _delay_loop_2) cykle zegara. Znając częstotliwość zegara możesz bardzo dokładnie przeliczyć sobie czasy opóźnień potrzebne do komunikacji po 1-Wire. W razie jakbyś miał problemy napisz to podeśle Ci działający kod.
  • #7 5038172
    czech_w
    Poziom 13  
    Posty: 80
    Pomógł: 1
    Ocena: 12
    Mam kolejne pytanie:
    Jeżeli układ testowy zasilam zasilaczem ATX (daje 5V) to mogę uszkodzić(spalić) DS18B20 ??
  • #8 5038199
    don diego
    Poziom 32  
    Posty: 1557
    Pomógł: 165
    Ocena: 63
    Nie spalisz, chyba że podłączysz odwrotnie ;)
  • #9 5038254
    czech_w
    Poziom 13  
    Posty: 80
    Pomógł: 1
    Ocena: 12
    Stany nie ustalone i inne dziwne rzeczy . Dmucham na zimne jak to elektryk a nie elektronik . Ksarim podesłał mi kod działający ale po modyfikacjach portów LCD i 1Wire wyświetla mi Temp. : 0 °C (nie znam się ale po mojemu nie widzi ds ale powinien pokazywać jak zobaczy ds'a 82,5 o ile dobrze pamiętam )
    PS czytam Datasheet'y :D
    Zapodałem oscyloskop i na DQ mam impulsy co ok 10 sek. :D
    Trochę nie ten przedział czasowy :D
    Szukam błędu :]
  • Pomocny post
    #10 5038593
    luap
    Poziom 12  
    Posty: 27
    Pomógł: 1
    Ocena: 2
    Witam , miałem niegdyś podobny problem , tyle że działam w Bascomie , lekarstwem było przestawienie procka w fusebitach na częstotliwość 8 MHz.
  • #11 5039455
    czech_w
    Poziom 13  
    Posty: 80
    Pomógł: 1
    Ocena: 12
    Sprawdziłem jeszcze raz fusebity i programator ISPPROG z 2004roku je źle ustawia przeprogramowałem ISPPROG 2007 i jest ok. czujnik działa :)
    Dzięki za pomoc.
  • #12 5385979
    Żyła
    Poziom 11  
    Posty: 6
    Mam pytanie związane z tym termometrem - czy procek wymusza stan wysoki na linii danych DQ magistrali 1WIRE na czas konwersji temperatury, w celu realizacji zasilania typu "parasite"?
    Jeśli nie - to czy pomiar jest możliwy ? Czy pomiar może być obarczony dużym błędem ze względu na zasilanie czujników jedynie przez rezystory 4k7 ?

    Moderowany przez crazy_phisic:

    "Klony" skasowałem. Regulamin 10.1

  • #14 5391253
    karol123
    Poziom 16  
    Posty: 228
    Pomógł: 2
    Ocena: 10
    Witam wszystkich na forum borykam się z podobnym problem tyle że jest program napisany w Bascomie nie mogę nawiązać łączności z układem DS 18B20 Mam Ds-a podłączonego pod Atemega 8 z podpięntą linią danych przez rezystor 4,7k i nic ciągle jest to samo zwraca 1 w ERR oto mój program
    bez wstępu

    config 1wire =portb.0
    declare sub 0dczyt
    Dim Temperatura (2) as byte
    Do
    Call Odczyt
    Cls
    if Temperatura (2)=0 Then
    LCD "Temp";Temperatura(1)
    Else
    LCD "Temp-"Temperatura(1)

    End If
    Loop
    End

    Sub Odczyt
    1wreset
    1wwrite &HCC
    1wwrite &H44
    Waitms 750
    1wreset
    1wwrite &HCC
    1wwrite &HBE

    temperatura(1)=wread(2)
    1wreset
    If Err=1 Then
    Cls
    LCD "Brak ukladu"
    Do
    Loop
    End IF
    If Temperatura(2)>0 Then
    Temperatura(1)=256-temperatura(1)
    End If
    Temperatura (1)=Temperatura(1)/2

    End Sub
  • #15 5391305
    snow
    Poziom 31  
    Posty: 1825
    Pomógł: 178
    Ocena: 201
    Co prawda nie znam bascoma ale czy w 2 linii zamiast 0(cyfra) nie powinno być O(litera) ?
  • #16 5563778
    Gabor
    Poziom 11  
    Posty: 54
    Ocena: 7
    Podobny problem zgłaszam..:(

    Korzystam z następującego gotowca :

    
    #include <avr/io.h>
    #include <stdlib.h>
    #include <util/delay.h>
    #include <stdio.h>
    #include "serial.h"
    
    
    
    //#include "HD44780.h"
    
    
    #ifndef F_CPU
    #define F_CPU 	8000000
    #endif
    
    
    #define WE 4
    #define PORT_1wire PIND
    #define SET_1wire DDRD&=~_BV(WE)
    #define CLEAR_1wire DDRD|=_BV(WE)
    
    char buff[8]; //zmienna do konwersji temperatury
    // reset magistarali
    
    unsigned char RESET_PULSE(void)
    {
    
    unsigned char PRESENCE;
    
    CLEAR_1wire;
    _delay_us(600);
    SET_1wire;
    
    _delay_us(50);
    
    
     
    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);
    //_delay_loop_1(5);
             if(bit==1)
                SET_1wire;
                _delay_us(80);
             //_delay_loop_1(80);
                SET_1wire;
    }
    
    unsigned char read(void)
    {
       unsigned char PRESENCE=0;
       
       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(void)
    {
       unsigned char i;
       unsigned char wartosc=0;
       
       for (i=0; i<8; i++)
       {
       if(read()) wartosc|=0x01<<i;
       _delay_us(15);
    
       }
    return(wartosc);
    }
    
    
    int check_temp(unsigned char *buf){
    
    	unsigned char sprawdz;
    	//char temp1=0, temp2=0;
    	unsigned char scratchpad[2] = {0};
    
    
        sprawdz=RESET_PULSE();
    
        if (sprawdz==1)
        {
            send_byte(0xCC);   
            send_byte(0x44);
           // _delay_ms(800);
    		
    		while(!read())
    			_delay_ms(10);
    
            sprawdz=RESET_PULSE();
            send_byte(0xCC);
            send_byte(0xBE);
    
           // temp1=read_byte();
           // temp2=read_byte();
    
            scratchpad[1] = read_byte();   //lsb
            scratchpad[0] = read_byte();	//msb
    		buf[0] = scratchpad[1];
    		buf[1] = scratchpad[0];
            sprawdz=RESET_PULSE();
    
    	ser_puts("AT ");
    	ser_puthex(scratchpad[0]);
    	ser_puthex(scratchpad[1]);
      /*  b = s / 100;
        ser_putc( b + '0');
    	b = s / 10;
    	b = b % 10;
        ser_putc( b + '0');
        b = s % 10;
        ser_putc( b + '0');*/
    	ser_putc(0x0d);
    	ser_putc(0x0a);
            float temp=0;
    		int tmp;
    	 	tmp = ((scratchpad[1] >>4) & 0x0f)|((scratchpad[0] <<4)& 0x70);
    
           // temp=(float)(temp1+(temp2*256))/16;
           // temp = ( (scratchpad[1] << 4) | (scratchpad[0] >> 4));
            //dtostrf(temp,1,1,buff);   //makefile w 7 linijce LIBS=-lm coby dzialalo
    		//utoa(temp,buf,10);
    	//	return temp;
            _delay_ms(500);
    		return tmp;
         }
    
    	 return 0;
    
    
    }
    


    Niestety z buforów msb i lsb dostaję wartosci 0x05 i 0x50 . ( 85 st C)

    Po przerobieniu funkcji pod delay_loop_2 ( dla 8 Mhz) w ten oto sposób:


    
    #include <avr/io.h>
    #include <stdlib.h>
    #include <util/delay.h>
    #include <stdio.h>
    #include "serial.h"
    
    
    
    //#include "HD44780.h"
    
    
    #ifndef F_CPU
    #define F_CPU 	8000000
    #endif
    
    
    #define WE 4
    #define PORT_1wire PIND
    #define SET_1wire DDRD&=~_BV(WE)
    #define CLEAR_1wire DDRD|=_BV(WE)
    
    char buff[8]; //zmienna do konwersji temperatury
    // reset magistarali
    
    unsigned char RESET_PULSE(void)
    {
    
    unsigned char PRESENCE;
    
    CLEAR_1wire;
    _delay_us(600);
    SET_1wire;
    
    _delay_us(50);
    
    
     
    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_loop_2(10000000);//_delay_us(5);
    //_delay_loop_1(5);
             if(bit==1)
                SET_1wire;
               _delay_loop_2(160000000); //  _delay_us(80);
             //_delay_loop_1(80);
                SET_1wire;
    }
    
    unsigned char read(void)
    {
       unsigned char PRESENCE=0;
       
       CLEAR_1wire;
       _delay_loop_2(4000000);//_delay_us(2);
    
       SET_1wire;
       _delay_loop_2(30000000);//;_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_loop_2(200000000);// _delay_us(100);
     
    }
    
    unsigned char read_byte(void)
    {
       unsigned char i;
       unsigned char wartosc=0;
       
       for (i=0; i<8; i++)
       {
       if(read()) wartosc|=0x01<<i;
       _delay_loop_2(30000000);//_delay_us(15);
    
       }
    return(wartosc);
    }
    
    
    int check_temp(unsigned char *buf){
    
    	unsigned char sprawdz;
    	//char temp1=0, temp2=0;
    	unsigned char scratchpad[2] = {0};
    
    
        sprawdz=RESET_PULSE();
    
        if (sprawdz==1)
        {
            send_byte(0xCC);   
            send_byte(0x44);
           // _delay_ms(800);
    		
    		while(!read())
    			_delay_ms(10);
    
            sprawdz=RESET_PULSE();
            send_byte(0xCC);
            send_byte(0xBE);
    
           // temp1=read_byte();
           // temp2=read_byte();
    
            scratchpad[1] = read_byte();   //lsb
            scratchpad[0] = read_byte();	//mmsb
    		buf[0] = scratchpad[1];
    		buf[1] = scratchpad[0];
            sprawdz=RESET_PULSE();
    
    	ser_puts("AT ");
    	ser_puthex(scratchpad[0]);
    	ser_puthex(scratchpad[1]);
      /*  b = s / 100;
        ser_putc( b + '0');
    	b = s / 10;
    	b = b % 10;
        ser_putc( b + '0');
        b = s % 10;
        ser_putc( b + '0');*/
    	ser_putc(0x0d);
    	ser_putc(0x0a);
            float temp=0;
    		int tmp;
    	 	tmp = ((scratchpad[1] >>4) & 0x0f)|((scratchpad[0] <<4)& 0x70);
    
           // temp=(float)(temp1+(temp2*256))/16;
           // temp = ( (scratchpad[1] << 4) | (scratchpad[0] >> 4));
            //dtostrf(temp,1,1,buff);   //makefile w 7 linijce LIBS=-lm coby dzialalo
    		//utoa(temp,buf,10);
    	//	return temp;
            _delay_ms(500);
    		return tmp;
         }
    
    	 return 0;
    
    
    }
    


    dostaję same jedynki..

    Może ktoś pomóc ?

    Dodano po 2 [minuty]:

    aaa rezystor podciągający 4.7 k jest, termometr na płytce, nie na kablu, połączenia sprawdzone...procesor Atmega 8 pracuje na 8 Mhz
  • #17 5563929
    HubertMD
    Poziom 11  
    Posty: 30
    Pomógł: 1
    Ja taż miałem taki problem podłączyłem ds18b20 trzema przewodami to zawsze miałem na nim stan wysoki i komunikacja była nie możliwa, gdy podłączyłem dwoma przewodami to zaczoł wykrywać mi DS'a ale cały czas dostawałem 85.0 mimo że czasy opóźnień były idealne. Pomogło mi dopiero zmniejszenie rezystora z 4,7kΩ do 2,3kΩ, słyszałem że w ten sposób ds może przekłamywać wyniki po przez samonagrzewanie się w czasie konwersji temperatury to też pomiar temperatury odbywa się mniej więcej co 1s.
  • #18 5564137
    Gabor
    Poziom 11  
    Posty: 54
    Ocena: 7
    Wsadziłem opornik 2.2 k 3.3 k nie pomaga...

    a mozesz udostępnić kod twojego programu obsługującego termometr ? Może te wartości u mnie nie są takie idealne. Patrzałem w dokumentacji z wykresów ciężko mi się zorientować, z przykładowych funkcji to właśnie są takie same.

    Dodano po 1 [godziny] 43 [minuty]:

    Ok działa... mój głupi błąd w lutowaniu: korzystam z płytki uniwersalnej i podpiąłem Vcc do lini wyglądającej jak "poprzeczne male Vcc" ale nie bedąca podpiętą do Vcc.. Jedno lutowanie i 24 h w plecy :(
    Ale za to działa nawet na 4.7 k bez z zasilaniem zewnętrznym :)

Podsumowanie tematu

✨ Problem dotyczył braku odczytu temperatury z czujnika DS18B20 podłączonego do mikrokontrolera ATMEGA8 z wyświetlaczem LCD. Główne przyczyny to brak podciągania linii danych 1-Wire, nieprawidłowe ustawienia fusebitów mikrokontrolera, błędy w opóźnieniach (delay) oraz nieodpowiednia implementacja funkcji opóźniających. Zalecano sprawdzenie obecności rezystora podciągającego 4,7 kΩ na linii danych, poprawne ustawienie częstotliwości zegara procesora (np. 8 MHz) oraz dokładne dostosowanie czasów opóźnień do komunikacji 1-Wire. Wskazano, że standardowe funkcje delay_us() i delay_ms() mogą nie być wystarczająco precyzyjne i warto stosować własne funkcje opóźniające oparte na pętlach assemblerowych. Problemy z komunikacją mogły wynikać także z błędów w lutowaniu i złego podłączenia zasilania. W przypadku zasilania z zasilacza ATX 5V czujnik nie ulega uszkodzeniu, o ile jest podłączony prawidłowo. Dodatkowo, w trybie zasilania typu "parasite" mikrokontroler powinien wymuszać stan wysoki na linii DQ podczas konwersji temperatury. W niektórych przypadkach zmniejszenie rezystora podciągającego z 4,7 kΩ do około 2,2 kΩ poprawiło stabilność odczytów. Po poprawnym ustawieniu fusebitów i podciąganiu linii czujnik zaczął poprawnie odpowiadać i wyświetlać temperaturę.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA