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

Niepoprawne wskazania temperatury DS18B20

_lukas 12 Gru 2009 10:38 2459 4
REKLAMA
  • #1 7377531
    _lukas
    Poziom 11  
    Witam

    Mam zbudowany układ na atmega 32 i do niego podpięte 4 czujniki DS18B20. Po włączeniu przez kilka godzin wszystkie pokazują właściwą temperaturę. Po tym czasie trzeci czujnik co jakiś czas pokazuje trzecie miejsce po przecinku, a czwarty czujnik również co jakiś czas pokazuje niewłaściwą temperaturę - w okolicach 130 stopni ( rzeczywista temperatura jest w okolicach 60 stopni). Wszystkie czujniki mam ustawione, aby zmieniały swoje wartości co 1/4 stopnia. Trzeci i czwarty również potrafią pokazać po przecinku inne cyfry niż 00, 25, 50, 75. Natomiast dwa pierwsze czujniki pokazują temperaturę właściwie. Co może być przyczyną?

    Pozdrawiam

    Kod mojego programu:
    #include <avr\io.h>
    #include <inttypes.h>
    #include <stdio.h>
    #include <avr\pgmspace.h>
    #include <util\delay.h>
    #include <math.h>
    #include <avr\interrupt.h>
    
    #include "makra.h"
    #include "harddef.h"
    #include "lcd.h"
    #include "switch.h"
    #include "crc8.h"
    #include "delay.h"
    #include "ds18x20.h"
    #include "onewire.h"
    
    //definicje
    #define MAXSENSORS 4
    #define DELTA_MAX 80
    #define DELTA_MIN 2
    #define CZAS_PRACY_MAX 99
    #define CZAS_PRACY_MIN 5
    //zmienne globalne
    
    
    uint8_t gSensorIDs[MAXSENSORS][OW_ROMCODE_SIZE];
    uint8_t i;
    uint8_t pom;
    uint8_t linia2;
    uint8_t pompa_czas=0;
    uint8_t pompa_status=0;
    char s[8];
    uint8_t subzero;
    uint8_t cel;
    uint8_t cel_frac_bits;
    double temp[MAXSENSORS];
    uint8_t tablica[3];
    
    uint8_t id[OW_ROMCODE_SIZE];
    
    //----------------
    
    //funkcje
    void zmiana (void)
    	{
    	if (linia2 >= 4) linia2=0;
    		else linia2++;
    	LCDgoto(2,1);
    	LCDstr("                ");
    	kursor_OFF();
    	switch (linia2)
    		{
    		case 0:
    			LCDgoto(2,1);
    			LCDstr("DELTA=          ");
    			sprintf(s, "%d", tablica[0]);
    			LCDgoto(2,7);
    			LCDstr(s);
    			break;
    		case 1:
    			LCDgoto(2,1);
    			LCDstr("temp_wyl=       ");
    			LCDgoto(2,10);
    			sprintf(s, "%d", tablica[1]);
    			LCDstr(s);
    			break;
    		case 2:
    			LCDgoto(2,1);
    			LCDstr("czas pracy=     ");
    			LCDgoto(2,12);
    			sprintf(s, "%d", tablica[2]);
    			LCDstr(s);
    			break;
    		case 3:
    			LCDgoto(2,1);
    			LCDstr("P=      ZB=     ");
    			break;
    		case 4:
    			LCDgoto(2,1);
    			LCDstr("praca pompy:    ");
    			break;
    			
    		}
    
    	}
    
    void plus (void) 
    	{
    	switch (linia2)
    		{
    		case 0:
    			if (tablica[0] < DELTA_MAX) tablica[0]++;
    			LCDgoto(2,7);
    			LCDstr("  ");
    			LCDgoto(2,7);
    			sprintf(s, "%d", tablica[0]);
    			LCDstr(s);
    			break;
    		case 1:
    			if (tablica[1] < (tablica[0]-2)) tablica[1]++;
    			LCDgoto(2,10);
    			LCDstr("  ");
    			LCDgoto(2,10);
    			sprintf(s, "%d", tablica[1]);
    			LCDstr(s);
    			break;
    		case 2:
    			if (tablica[2] < CZAS_PRACY_MAX) tablica[2]++;
    			LCDgoto(2,12);
    			LCDstr("  ");
    			LCDgoto(2,12);
    			sprintf(s, "%d", tablica[2]);
    			LCDstr(s);
    			break;
    	
    		}
    
    
    
    	}
    
    void minus (void)
    	{
    		switch (linia2)
    		{
    		case 0:
    			if ((tablica[0] > DELTA_MIN) && (tablica[0] > (tablica[1]+2))) tablica[0]--;
    			LCDgoto(2,7);
    			LCDstr("  ");
    			LCDgoto(2,7);
    			sprintf(s, "%d", tablica[0]);
    			LCDstr(s);
    			break;
    		case 1:
    			if (tablica[1] > 1) tablica[1]--;
    			LCDgoto(2,10);
    			LCDstr("  ");
    			LCDgoto(2,10);
    			sprintf(s, "%d", tablica[1]);
    			LCDstr(s);
    			break;
    		case 2:
    			if (tablica[2] > CZAS_PRACY_MIN) tablica[2]--;
    			LCDgoto(2,12);
    			LCDstr("  ");
    			LCDgoto(2,12);
    			sprintf(s, "%d", tablica[2]);
    			LCDstr(s);
    			break;
    		}
    	}
    
    void pompa_start_manual (void) 
    	{
    	if (PINC&1<<5)
    	{ 
    	PORTA&=~(1<<7);
    	PORTB&=~(1<<4);
    	PORTA|=(1<<6);
    	pompa_czas=tablica[2];
    	linia2=3;
    	zmiana();
    	pompa_status=1;
    	} else PORTA&=~(1<<6);
    	}
    
    
    void pompa_stop_manual (void)
    	{
    	
    	PORTA|=1<<7;
    	PORTB|=1<<4;
    	PORTA|=1<<6;
    	pompa_status=0;
    	pompa_czas=0;
    	linia2=2;
    	zmiana();
    	}
    void pompa_start (void) 
    	{
    	if (PINC&1<<5)
    	{
    	PORTA&=~(1<<7);
    	PORTB&=~(1<<4);
    	PORTA|=(1<<6);
    	}else PORTA&=~(1<<6);
    	}
    
    void pompa_stop (void)
    	{
    	PORTA|=1<<7;
    	PORTB|=1<<4;
    	if (pompa_status==1)
    	{
    	pompa_stop_manual();
    	}
    	}
    
    
    
    
    //program
    int main(void)
    {
    //----------------------------------------------
    	
    	//deklaracja portów wyświetlacza
    	DDR(LCD_DPORT) = 1<<LCD_E | 1<<LCD_RS | 
    		0x0F<<LCD_D4;
    	
    	//deklaracja portów przycisków
    	SWPORT = 1<<SW1 | 1<<SW2| 1<<SW3 | 1<<SW4 | 1<<SW5 | 1<<POM;
    
    	/* ustawienie wyjsc*/
    	DDRA=0xFF;
    	PORTA=0xFF;
    	
    	DDRB=0x10;
    	PORTB=0x10;
    
    	//deklaracja magistrali one-wire
    	#ifndef OW_ONE_BUS
    	ow_set_bus(&PINB,&PORTB,&DDRB,PB0);
    	#endif
    
    
    	// Timer0
    	TCCR0 = 1<<CS01|1<<CS00; 
    	TIMSK = 1<<TOIE0; 
    
    
    //przypisanie ROMu 0 termometru
     	gSensorIDs[0][0]=40;
    	gSensorIDs[0][1]=166;
    	gSensorIDs[0][2]=205;
    	gSensorIDs[0][3]=239;
    	gSensorIDs[0][4]=1;
    	gSensorIDs[0][5]=0;
    	gSensorIDs[0][6]=0;
    	gSensorIDs[0][7]=70;
    
    //przypisanie ROMu 1 termometru
     	gSensorIDs[1][0]=40;
    	gSensorIDs[1][1]=15;
    	gSensorIDs[1][2]=255;
    	gSensorIDs[1][3]=239;
    	gSensorIDs[1][4]=1;
    	gSensorIDs[1][5]=0;
    	gSensorIDs[1][6]=0;
    	gSensorIDs[1][7]=139;
    
    //przypisanie ROMu 2 termometru
     	gSensorIDs[2][0]=40;
    	gSensorIDs[2][1]=112;
    	gSensorIDs[2][2]=231;
    	gSensorIDs[2][3]=239;
    	gSensorIDs[2][4]=1;
    	gSensorIDs[2][5]=0;
    	gSensorIDs[2][6]=0;
    	gSensorIDs[2][7]=117;
    
    //przypisanie ROMu 3 termometru
     	gSensorIDs[3][0]=40;
    	gSensorIDs[3][1]=80;
    	gSensorIDs[3][2]=7;
    	gSensorIDs[3][3]=240;
    	gSensorIDs[3][4]=1;
    	gSensorIDs[3][5]=0;
    	gSensorIDs[3][6]=0;
    	gSensorIDs[3][7]=187;
    
    //zmienne zapisane
    	tablica[0]=36; //delta
    	tablica[1]=31; //temp_wyl różnica przy której ma się wyłączyć
    	tablica[2]=30; //czas pracy pompy włączonej ręcznie
    
    //temp[0] - temperatura wejścia na instalzacje
    //temp[1] - temperatura powrotu z instalacji
    //temp[2] - temperatura pieca
    //temp[3] - temperatura 1 zbiornika
    
    //zmienna pomocnicza do wyświetlania 2 linii
    linia2=3;
    
    //inicjacja LCD
    	LCDinit();
    	LCDcls();
     
    	
    
    for (int j=0;j<4;j++)
    	{
    	//przepisanie ROMu termometru 1 do zmiennej
    		for (i=0;i<OW_ROMCODE_SIZE;i++)
    			{
    			id[i]=gSensorIDs[j][i];
    			}
    
    		//pomiar termeratury 10 bit	
    			ow_reset(); 
    			if( ow_input_pin_state() ) 
    				{ 
    				ow_command( DS18X20_WRITE_SCRATCHPAD, id );
    				ow_byte_wr(75);
    				ow_byte_wr(70);
    				ow_byte_wr(63); 
    				} 
    	}
    
    //napisy stałe na LCD
    LCDcls();
    LCDgoto(1,1);
    LCDstr("C=");
    LCDgoto(1,9);
    LCDstr("Z=");
    LCDgoto(2,13);
    LCDstr("D=");
    LCDgoto(2,1);
    LCDstr("P=");
    LCDgoto(2,9);
    LCDstr("ZB=");
    pom=1;
    kursor_OFF();
    
    //włączenie przerwań
    	sei();
    
    //główna pętla programu - nieskończona
    	for(;;) 
    		{
    				
    			for (i=0;i<4;i++)
    				{
    					if ( DS18X20_start_meas(DS18X20_POWER_PARASITE,&gSensorIDs[i][0]) == DS18X20_OK ) 
    					{
    						delay_ms(DS18B20_TCONV_12BIT/4);
    					
    					
    						if ( DS18X20_read_meas( &gSensorIDs[i][0], &subzero, &cel, &cel_frac_bits) == DS18X20_OK ) 
    							{
    							temp[i]=cel+(double)cel_frac_bits/16;
    							}
    					}
    				}
    
    		
    		LCDgoto(1,3);
    		sprintf(s, "%.2f", temp[0]);
    		LCDstr(s);
    		
    		LCDgoto(1,11);
    		sprintf(s, "%.2f", temp[1]);
    		LCDstr(s);
    		
    		
    		
    
    		Przyc(1<<SW1, zmiana);
    
    		if (linia2==3)
    			{
    			LCDgoto(2,3);
    			sprintf(s, "%.2f", temp[2]);
    			LCDstr(s);
    			LCDgoto(2,12);
    			sprintf(s, "%.2f", temp[3]);
    			LCDstr(s);
    			}
    
    
    		Przycisk(1<<SW2, plus);
    		Przycisk(1<<SW3, minus);
    
    		Przyc(1<<SW4, pompa_start_manual);
    		Przyc(1<<SW5, pompa_stop_manual);
    		Przyc(1<<POM, pompa_stop);
    
    		if (pompa_status==1) //pompa załączona ręcznie
    			{
    			if (pompa_czas>0)
    				{
    				pompa_czas--;
    				if (linia2==4)
    					{
    					LCDgoto(2,13);
    					LCDstr("  ");
    					LCDgoto(2,13);
    					sprintf(s,"%d",pompa_czas);
    					LCDstr(s);
    					};
    				}else
    					{
    					pompa_stop_manual();
    					}
    			}
    
    		if (pompa_status==0)	
    		{
    		if ((temp[0] - temp[1]) > tablica[0]) pompa_start();
    			else if ((temp[0] - temp[1]) < tablica[1]) pompa_stop();
    		}
    	}
    
    
    return 0;
    }
    
  • REKLAMA
  • #2 7378595
    xury
    Specjalista automatyka domowa
    Nie wiem czy to co napiszę jest trafne, bo kompletnie nie znam C.
    Moja hipoteza to zapełnienie stosu, po kilku godzinach i nachodzenie na wartości zmiennych.
    Możliwe, że to kompletna herezja tym niemniej takie przypadki na Bascomie bywały.
  • REKLAMA
  • #3 7383006
    GienekS
    Poziom 32  
    Tak na szybko, włączasz przerwania ale ja nigdzie nie widzę żadnej obsługi przerwania.
  • REKLAMA
  • #4 7383046
    _lukas
    Poziom 11  
    Obsługę przerwań mam w innym pliku

    #include <avr\interrupt.h>
    #include <avr\io.h>
    #include <inttypes.h>
    #include <stdio.h>
    #include <avr\pgmspace.h>
    #include <util\delay.h>
    #include <math.h>
    #include "onewire.h"
    #include "makra.h"
    #include "harddef.h"
    #include "lcd.h"
    #include "switch.h"
    
    volatile uint8_t g_bDelay; 
    //przycisk
    
    void Przycisk(uint8_t maska, void(*proc)(void) )
    {
    	if(!(SWPIN & maska))
    	{
    		// usuwanie drgań styków
    		g_bDelay = 6; //50ms
    		while(g_bDelay != 0) {}
    		if(!(SWPIN & maska))
    		{
    			proc(); 
    			g_bDelay = 48; //1s
    			do
    			{
    				if(g_bDelay==0)
    				{
    					g_bDelay = 24; //50ms
    					proc(); 
    				}
    			}while(!(SWPIN & maska));
    		}
    	}
    }
    
    void Przyc(uint8_t maska, void(*proc)(void) )
    {
    	if(!(SWPIN & maska))
    	{
    		// usuwanie drgań styków
    		g_bDelay = 6; //50ms
    		while(g_bDelay != 0) {}
    		if(!(SWPIN & maska))
    		{
    			proc(); 
    			g_bDelay = 48; //1s
    
    		}
    	}
    }
    
    
    
    
    // Obsługa przerwań
    SIGNAL(SIG_OVERFLOW0)
    {
    	// Wpisanie do licznika początkowej wartości
    	TCNT0 = 1; 
    	
    		// Zmienna zapobiegająca niepotrzebnemu kopiowaniu zmiennej g_bDelay (typ volatile!)
    		uint8_t delay; 
    	
    		// Obsługa opóźnień
    		delay = g_bDelay; 
    		if(delay > 0)
    		{
    			--delay; 
    			g_bDelay = delay; 
    		}
    
    	
    }
  • #5 13730877
    _lukas
    Poziom 11  
    Przy ostatnim czujniku dołączyłem kondensator i problem się rozwiązał.
REKLAMA