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

Atmega32+DS18B20 czy wina leży po stronie czasów opóźnień?

mazi35 18 Paź 2008 12:33 1882 7
REKLAMA
  • #1 5643414
    mazi35
    Poziom 17  
    Witam,
    Na wyświetlaczu zamiast temperatury widnieje 1279-nijak to się ma do temperatury(w pokoju jest wyższa o ładne 10 stopni). Stąd moje pytanie czy to czasy opóźnień mogą tak działać?
    Poniżej kod:

    #include <avr/io.h>
    #include <avr/pgmspace.h>
    #include <stdlib.h>
    #include "1wire.h"
    
    
    //==========================================LCD================================================== 
    #define F_CPU 16000000UL
    #define F_OSC 16000000UL
    
    #define cbi(sfr, b) (sfr &= ~(1<<b))
    #define sbi(sfr, b) (sfr |= (1<<b)) 
    
    #define LCD PORTA
    #define LCDD DDRA
    
    #define LCD2 PORTC
    #define LCDD2 DDRC
    
    #define E  6
    #define RS  7
    
    #define SET_E   sbi(LCD2, E)
    #define CLR_E   cbi(LCD2, E)
    
    #define SET_RS  sbi(LCD2, RS)
    #define CLR_RS  cbi(LCD2, RS)
    
    
    //////////////////////////////////////
    void delay(void);
    
    void write_to_lcd(char x);
    void LCDkomenda(char L_dane);
    void LCDznak(char L_dane);
    void LCD_clr(void);
    void LCDnapis(char * s);
    void LCD_xy(char x, char y);
    void LCD_putint(int L_liczba);
    
    
    
    //NA 2 CZUJNIKI POMIAROWE
    signed char TLs[2];
    signed char THs[2];
    
    static inline void delayloop16(unsigned int count)
    {
    	asm volatile (  "cp  %A0,__zero_reg__ \n\t"  \
                         "cpc %B0,__zero_reg__ \n\t"  \
                         "breq L_Exit_%=       \n\t"  \
                         "L_LOOP_%=:           \n\t"  \
                         "sbiw %0,1            \n\t"  \
                         "brne L_LOOP_%=       \n\t"  \
                         "L_Exit_%=:           \n\t"  \
                         : "=w" (count)
    					 : "0"  (count)
                       );                            
    }
    
    #define DELAY_US_CONV(us) ((uint16_t)(((((us)*1000L)/(1000000000/F_OSC))-1)/4))
    #define delay_us(us)	  delayloop16(DELAY_US_CONV(us))
    
    
    /*void delay_us(unsigned int dl)
    {
    int i,j;
    for(i=dl;i>=0;i--)
    	{
    	for(j=16;j>=0;j--)
    	asm volatile("nop");
    	}
    }
    */
    void delay_ms(unsigned int dl)
    {
    volatile int i;
    for(i=dl;i>=0;i--)
    	{
    	delay_us(1000);
    	}
    }
    
    
    //short int x;
    unsigned char gSensorIDs[2];
    
    
    main()
    {
    LCDD=0xFF;
    LCDD2=0xFF;
    
    char i,j;
    
    
    
    //clear
    LCDkomenda(0x01);
    //Function SET
    LCDkomenda(0x2F);
    //Display on
    LCDkomenda(0x0F);
    //Entry mode
    LCDkomenda(0x06);
    //return home
    LCDkomenda(0x03);
    
    
    
    
    
    //WYSZUKANIE ADRESU 1-WIRE
    gSensorIDs[0]=OWFirst();
    gSensorIDs[1]=OWNext();
    
    
    
    
    
    THs[0]=45;
    TLs[0]=10;
    
    
    //	ow_set_bus(DS_PORT1);	
    //	if (gSensorIDs[0][0] != 255) config_18b20(TLs[0], THs[0], &gSensorIDs[0][0]);
    
    	delay_ms(1);
    
       while(1)
       {
    	if (gSensorIDs[0])
    		{	
            LCD_clr();
    		//ow_set_bus( DS_PORT1);
    		//LCD_18b20_multidrop(&gSensorIDs[0][0]);
    		ow_Send_Convert_Temp();
    		delay_ms(1000);
    		LCD_putint(ow_HiResTemp(gSensorIDs[0]));
    
    
    		delay_ms(2000);
    
    		}
    		else
    		{
    		LCD_clr();
    		LCDnapis("brak czujnika");
    //			ow_set_bus(DS_PORT1);
    //	search_sensors(&gSensorIDs[0][0]);
    
    		delay_ms(5000);
    		}
    
    	}
    	
    
    
    }
    
    
    void delay(void)
    {
    	//unsigned int iter2=0;
    	unsigned int iter=0;
    	//for(iter2=0;iter2<10;iter2++)
    	for(iter=0;iter<10000;iter++)asm("nop");
    }
    
    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
    
    	//delay();
    	
    
    	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
    
    	PORTB=0x01;
    	delay();
    	PORTB=0x00;
    	delay();
    
    
    }
    
    void LCDkomenda(char L_dane)
    {
    	CLR_RS; // niski stan na RS -> zapis instrukcji
    	write_to_lcd(L_dane); // zapis do LCD
    }
    
    void LCDznak(char L_dane)
    {
    	SET_RS; // niski stan na RS -> zapis instrukcji
    	write_to_lcd(L_dane); // zapis do LCD
    }
    
    void LCD_clr(void)
    {
    	//clear
    	LCDkomenda(0x01);
    	LCD_xy(0,0);
    }
    
    void LCDnapis(char * s)
    {
    	while(*s) // do napotkania 0
      	{
      		LCDznak(*s); // zapisz znak wskazywany przez s na LCD
      		s++; // zwiększ s (przygotuj nastepny znak)
      	}
    }
    
    void LCD_xy(char x, char y)
    {
       switch(y)
       {
          case 1: y=0x40; break;
          case 2: y=0x14; break;
       }
       LCDkomenda(0x80+y+x);
    }
    
    void LCD_putint(int L_liczba)
    {
    	char tab[10];
    	sprintf(tab,"%d",L_liczba);
    	LCDnapis(tab);
    }
    
    
    


    pozdrawiam
  • REKLAMA
  • #2 5643475
    elektryk
    Poziom 42  
    Jeśli temperatura się zmienia to winą jest procedura konwersji, jeśli temperatura jest stała to bym się zgodził że winne są timingi. Ponieważ nie korzystasz z własnych procedur komunikacyjnych najlepszym rozwiązaniem będzie pomiar timingów oscyloskopem.
  • REKLAMA
  • #3 5646257
    mazi35
    Poziom 17  
    Witam
    Czy istnieje sposób inny niż oscyloskop jeżeli chodzi o te opóźnienia?
    pozdrawiam
  • REKLAMA
  • #4 5653232
    marcus747
    Poziom 1  
    Jeśli wyswietla wartość 127,9 to znaczy ze z czujnika ida same wartości FF. Z doświadczenia wiem że taki stan rzeczy powoduje błędne podłączenie czujnika! Patrz dokumentacja ( ale w niej widok nóżek od spodu czujnika!!). Jeśli raz to źle podepniesz juz zwsze będzie pokazywał 127,9...... Jesli chodzi o poprawność transmisji to napisz sobie krótki programik który odczyta z czujnika jego adres tylko i wyświetli na lcd. jesli to zadziała ( a odczyt adresu działa zawsze nawet na padniętym czujniku !!) to transmisja jest ok a wina leży po stronie źle podpiętego czujnika.
  • REKLAMA
  • #5 5653291
    kred
    Poziom 20  
    Witam,

    Ja obsługę DS18b20 na AVRku zrobiłem bez pomocy oscyloskopu. Najpierw zacząłem od resetu magistrali - najprościej jest wyświetlić na LCD czy jakiś układ na magistrali odpowiedział na sygnał resetu. Potem już jest z górki :)

    Pozdrawiam i życzę powodzenia,
    Krzysiek
  • #6 5653294
    mazi35
    Poziom 17  
    kred napisał:
    Witam,

    Ja obsługę DS18b20 na AVRku zrobiłem bez pomocy oscyloskopu. Najpierw zacząłem od resetu magistrali - najprościej jest wyświetlić na LCD czy jakiś układ na magistrali odpowiedział na sygnał resetu. Potem już jest z górki :)

    Pozdrawiam i życzę powodzenia,
    Krzysiek


    Witam

    A mógłbyś zerknąć na ten kod powyżej?
    Może coś przeoczyłem?

    pozdrawiam i dzięki za rady

    PS. czujnik raczej podpiety ok
  • #7 5656379
    kred
    Poziom 20  
    Z tego co widzę to są tu duże opóźnienia (1s, 2s) - w nocie do ds18b20 masz wypisane minimalne czasy - u mnie one zadziałały. Nie widzę implementacji funkcji do 1wire, pewnie używasz czyjeś biblioteki. Też kiedyś tak chciałem zrobić i mi się nie powiodło. Wtedy napisałem swoją - Tobie też zalecam taką stworzyć. Może jak wrócę z pracy to wstawię swój kod.

    A takie pytanie - masz może podpięty pull-up do magistrali?
  • #8 5657832
    kred
    Poziom 20  
    Dobra, na początek kawałek kodu odpowiedzialnego za reset magistrali:

    #include <avr/io.h>
    
    #ifndef F_CPU
    #define F_CPU 4000000UL
    #endif
    #include <util/delay.h>
    
    #define OWIRE_DDR DDRD
    #define OWIRE_PORT PORTD
    #define OWIRE_INPORT PIND
    #define OWIRE_PIN 2
    
    char owire_reset()
    {
        char ret = 0;
        
        OWIRE_DDR |= (1 << OWIRE_PIN);
        OWIRE_PORT |= (1 << OWIRE_PIN);
        OWIRE_PORT &= ~(1 << OWIRE_PIN);
        _delay_us(500);
        OWIRE_DDR &= ~(1 << OWIRE_PIN);
        _delay_us(100);
        ret =  OWIRE_INPORT & (1 << OWIRE_PIN);
        _delay_us(150);
      
        return ret;
    }


    Funkcja reset zwraca wartość różną od zera w przypadku gdy nie ma odpowiedzi na magistrali.
    Żeby nie było tak łatwo, dalsze funkcje już sam napisz :) Hint: rozbij wysyłanie danych na 3 funkcje:
    - wysyłanie jedynki
    - wysyłanie zera
    - wysyłanie bajtu (korzysta z w/w funkcji)

    Życzę powodzenia!

    --
    P.S. Zapomniałem dodać, że w/w timingi są dla podłączonego czujnika z zasilaniem, nie dla (chyba to sie tak nazywa) parasite powered.
REKLAMA