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

[Atmega8] IW-18 i 2xDS-18b20 losowo gubi pomiar

Krokus22 13 Gru 2010 02:31 1627 4
REKLAMA
  • #1 8861977
    Krokus22
    Poziom 19  
    Witam wszystkich, w temacie mikrokontrolerów nie jestem zbyt mocny, dlatego proszę o pomoc. Postanowiłem zbudować termometr dwupunktowy na ds18b20 i wysterować multipleksując IW-18. Poniższy program działa, jego mankamentem jest losowy zanik pomiaru w jednym (IN) albo drugim (OUT) czujniku, czasem przekłamuje na sekundę pomiar, podając 80 stopni, jednak po chwili wraca do normy, obsługa multipleksu jest moja, natomiast czujników temp. wzorowana na kursie C dioda. Podejrzewam, że problem leży w programie, proszę o pomoc w lokalizacji błędu. Oto kody:

    main.c:
    
    
    
    /*
       Plik "main.c"
    
    */
    
    #include <stdio.h>
    #include <avr/io.h>
    #include <util/delay.h>
    #include "ds18b20.h"
    #include <avr/interrupt.h>
    #include <inttypes.h>
    
    #define F_CPU 8000000L
    
    
    
    void wyswietl(uint8_t cyfra) { /* instrukcja wyswietla zadane cyferki na wyswietlaczu led */
    	switch (cyfra){
    		case 0:
    			PORTD = 0b11000000;
    			break;
    		case 1:
    			PORTD = 0b11111001;
    			break;
    		case 2:
    			PORTD = 0b10100100;
    			break;
    		case 3:
    			PORTD = 0b10110000;
    			break;
    		case 4:
    			PORTD = 0b10011001;
    			break;
    		case 5:
    			PORTD = 0b10010010;
    			break;
    		case 6:
    			PORTD = 0b10000010;
    			break;
    		case 7:
    			PORTD = 0b11111000;
    			break;
    		case 8:
    			PORTD = 0b10000000;
    			break;
    		case 9:
    			PORTD = 0b10010000;
    			break;
    		case 10:
    			PORTD = 0b11111111; //czysty ekran
    			break;			
    		case 11:
    			PORTD = 0b01111111;
    			break;
    		case 12: //minus
    			PORTD = 0b10111111;
    			break;
    				
    		default :
    			PORTD = 0b11111111;
    			break;
    			}
    	}
    
    	void wyswietl_kropke(void){
    	PORTD ^= 0x80;
    	}
    
    
    
    
    
    volatile uint8_t wysw=0; // zmienna oznaczająca numer aktywnego wyświetlacza
    
    
    volatile uint8_t  minus_in;
    volatile uint8_t  dziesiatki_in;
    volatile uint8_t  jednosci_in;
    volatile uint8_t  poprzecinku_in;
    
    volatile uint8_t  minus_out;
    volatile uint8_t  dziesiatki_out;
    volatile uint8_t  jednosci_out;
    volatile uint8_t  poprzecinku_out;
    
    
    int main(void)
    {
      
      
      /* Wszystkie linie portu D będą wyjściami */
       DDRD = 0xFF;  /* 0xFF binarnie 1111 1111 */
       DDRB = 0xFF;
       
    
    
    
    	/* Obsługa przerwań - multipleksowanie*/
    
        TCCR1B |= (1 << WGM12); // Ustawia timer1 w tryb CTC	
        OCR1A = 2073; // Ustawia wartość pożądaną na 100Hz dla preskalera 64
        TCCR1B |= (1 << CS11);
        TIMSK |= (1 << OCIE1A); // Zezwolenie na przerwania dla CTC
        sei(); // Zezwolenie globalne na przerwania
    
    
     
      /* Zmienna przechowuje aktualną wartość temperatury */        
      double temp_1;
      double temp_2;
      /* W tablicy zapisywane będą dane odczytane z układu ds18b20 */
      unsigned char ds18b20_pad_1[9]; //bylo 9
      unsigned char ds18b20_pad_2[9];
      
    
     
     
     
     while(1)
      {
    	
    	/* Funkcja 'ds18b20_ConvertT' wysyła do układu ds18b20 
           polecenie pomiaru czujnika 1*/      
         if(ds18b20_ConvertT_1())
        {
    
    		/* 750ms - czas konwersji */
           _delay_ms(750);  
                
    		ds18b20_Read_1(ds18b20_pad_1);  
    	    temp_1 = ((ds18b20_pad_1[1] << 8) + ds18b20_pad_1[0]) / 16.0 ;
    		
    
    
    		int liczba1=(int)(temp_1*10);
    		//minus_out=0;
    		dziesiatki_in = (uint8_t)(liczba1/100);
    
    		jednosci_in= (uint8_t)((liczba1/10)%10);
    
    		poprzecinku_in= (uint8_t)(liczba1%10);	
    		
    
        }
     
     //Drugi czujnik
     
     if(ds18b20_ConvertT_2())
        {
    
    		/* 750ms - czas konwersji */
           _delay_ms(750);  
                 
    		ds18b20_Read_2(ds18b20_pad_2); 
    		temp_2 = ((ds18b20_pad_2[1] << 8) + ds18b20_pad_2[0]) / 16.0 ;  
    
    
    		_delay_ms(1);
    		int liczba2=(int)(temp_2*10);
    		//minus_out=0;
    		dziesiatki_out = (uint8_t)(liczba2/100);
    
    		jednosci_out= (uint8_t)((liczba2/10)%10);
    
    		poprzecinku_out= (uint8_t)(liczba2%10);
    	   
    	
        }
    	
     
     }
    
    
    }
    
    
    ISR(TIMER1_COMPA_vect)
    {
        switch (wysw)
        {
     		case 0:
    			PORTB = 0b11111110;
    			wyswietl(poprzecinku_in);
    			wysw++;
    			break;
    		case 1:
    			PORTB= 0b11111101;
    			wyswietl(jednosci_in);
    			wyswietl_kropke();
    			wysw++;
    			break;
    		case 2:
    			PORTB= 0b11111011;
    			wyswietl(dziesiatki_in);
    			wysw++; 
    			break;
    		case 3:
    			PORTB= 0b11110111;
    			wyswietl(10);
    			wysw++;
    			break;
    		case 4:
    			PORTB= 0b11101111;
    			wyswietl(10);
    			wysw++;
    			break;
    		case 5:
    			PORTB= 0b11011111;
    			wyswietl(poprzecinku_out);
    			wysw++;
    			break;
    		case 6:
    			PORTB= 0b10111111;
    			wyswietl(jednosci_out);
    			wyswietl_kropke();
    			wysw++;
    			break;
    		case 7:
    			PORTB= 0b01111111;
    			wyswietl(dziesiatki_out);
    			wysw=0;
    			break;
    
    		}
    	
    		
        }
    
    



    ds18b20.c :




    
    
    /*
       Plik ds18b20.c
       (minimum kodu do odczytu temperatury z ds18b20)
    
       xyz.isgreat.org
    */
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include "ds18b20.h"
    
    
    /**********************************************************/
    
    unsigned char ds18b20_ConvertT_1(void)
    {
      if (!OneWireReset_1()) return 0;
    
      OneWireWriteByte_1(0xcc); // SKIP ROM
      OneWireWriteByte_1(0x44); // CONVERT T
    
      return -1;
    }
    
    
    unsigned char ds18b20_ConvertT_2(void)
    {
      if (!OneWireReset_2()) return 0;
    
      OneWireWriteByte_2(0xcc); // SKIP ROM
      OneWireWriteByte_2(0x44); // CONVERT T
    
      return -1;
    }
    
    
    
    /***********************************************************/
    
    int ds18b20_Read_1(unsigned char scratchpad[])
    {
      unsigned char i;    
    
      if (!OneWireReset_1()) return 0;
    
      OneWireWriteByte_1(0xcc); // SKIP ROM
      OneWireWriteByte_1(0xbe); // READ SCRATCHPAD
    
      for(i=0; i<10; i++) scratchpad[i] = OneWireReadByte_1();
     
      return 1;
    }
    
    /**********************************************************/
    
    int ds18b20_Read_2(unsigned char scratchpad[])
    {
      unsigned char i;    
    
      if (!OneWireReset_2()) return 0;
    
      OneWireWriteByte_2(0xcc); // SKIP ROM
      OneWireWriteByte_2(0xbe); // READ SCRATCHPAD
    
      for(i=0; i<10; i++) scratchpad[i] = OneWireReadByte_2(); //i<10
     
      return 1;
    }
    
    
    
    
    
    
    /**********************************************************/
    
    void OneWireStrong_1(char s)
    {
      if (s)
      {
         SET_ONEWIRE_PORT_1; 
         SET_OUT_ONEWIRE_DDR_1; 
      }
      else
      {
         SET_IN_ONEWIRE_DDR_1; 
      }
    }
    
    /**********************************************************/
    
    
    void OneWireStrong_2(char s)
    {
      if (s)
      {
    	 SET_ONEWIRE_PORT_2; 
    	 SET_OUT_ONEWIRE_DDR_2;
      }
      else
      { 
    	 SET_IN_ONEWIRE_DDR_2; 
      }
    }
    
    /**********************************************************/
    
    
    
    unsigned char OneWireReset_1()
    {
      CLR_ONEWIRE_PORT_1; 
    
      if (!(IS_SET_ONEWIRE_PIN_1)) return 0;  
    
      SET_OUT_ONEWIRE_DDR_1; 
      _delay_us(500); //bylo 500
      SET_IN_ONEWIRE_DDR_1; 
      _delay_us(70); //bylo 70
    
      if(!(IS_SET_ONEWIRE_PIN_1))
      {
        _delay_us(500); //bylo 500
        return(1);
      }
    
      _delay_us(500); //bylo 500
    
    return(0);
    }
    
    /**********************************************************/
    
    unsigned char OneWireReset_2()
    {
      CLR_ONEWIRE_PORT_2; 
    
      if (!(IS_SET_ONEWIRE_PIN_2)) return 0;  
     
      SET_OUT_ONEWIRE_DDR_2; 
      _delay_us(500); //bylo 500 
      SET_IN_ONEWIRE_DDR_2; 
      _delay_us(70); //bylo 70
    
      if(!(IS_SET_ONEWIRE_PIN_2))
      {
        _delay_us(500); //bylo 500
        return(1);
      }
    
      _delay_us(500); //bylo 500
    
    return(0);
    }
    
    /**********************************************************/
    
    
    
    
    
    
    void OneWireWriteByte_1(unsigned char byte)
    {
       unsigned char i;
    
       CLR_ONEWIRE_PORT_1; 
    
       for (i=0; i<8; i++)
       {
         SET_OUT_ONEWIRE_DDR_1; 
    
         if (byte & 0x01)
         {
           _delay_us(7);
           SET_IN_ONEWIRE_DDR_1; 
           _delay_us(70);
         }
         else
         {
            _delay_us(70); //bylo 70
            SET_IN_ONEWIRE_DDR_1; 
    		
            _delay_us(7); //bylo 7
         }
    
         byte >>= 1;
       }
    }
    
    /***********************************************************/
    
    
    
    
    
    
    void OneWireWriteByte_2(unsigned char byte)
    {
       unsigned char i;
    
       CLR_ONEWIRE_PORT_2; 
    
       for (i=0; i<8; i++)
       {
    	 SET_OUT_ONEWIRE_DDR_2; 
    
         if (byte & 0x01)
         {
           _delay_us(7);
    	   SET_IN_ONEWIRE_DDR_2; 
           _delay_us(70);
         }
         else
         {
            _delay_us(70); //bylo 70
    		SET_IN_ONEWIRE_DDR_2; 
    		
            _delay_us(7); //bylo 7
         }
    
         byte >>= 1;
       }
    }
    
    
    
    
    
    
    
    unsigned char OneWireReadByte_1(void)
    {
      unsigned char i, byte = 0;
    
      SET_IN_ONEWIRE_DDR_1; 
      
      for (i=0; i<8; i++)
      {
         SET_OUT_ONEWIRE_DDR_1; 
         _delay_us(7);
         SET_IN_ONEWIRE_DDR_1; 
         _delay_us(7); //bylo 7
         byte >>= 1;
         
         if(IS_SET_ONEWIRE_PIN_1) byte |= 0x80;
    
         _delay_us(70); //bylo 70
      }
    
      return byte;
    }
    
    
    unsigned char OneWireReadByte_2(void)
    {
      unsigned char i, byte = 0;
     
      SET_IN_ONEWIRE_DDR_2; 
      
      for (i=0; i<8; i++)
      {
    	 SET_OUT_ONEWIRE_DDR_2; 
         _delay_us(7);
    	 SET_IN_ONEWIRE_DDR_2; 
         _delay_us(7);
         byte >>= 1;
         
         if(IS_SET_ONEWIRE_PIN_2) byte |= 0x80;
    
         _delay_us(70);
      }
    
      return byte;
    }
    
    
    
    



    ds18b20.h:
    
    
    /*
       Plik ds18b20.h
    
       (xyz.isgreat.org)  
    */
    
    #ifndef DS18B20_H
    #define DS18B20_H
    
    /* DS18B20 przyłączony do portu  Pc1 AVRa  */
    #define SET_ONEWIRE_PORT_1     PORTC  |=  _BV(1)
    #define CLR_ONEWIRE_PORT_1     PORTC  &= ~_BV(1)
    #define IS_SET_ONEWIRE_PIN_1   PINC   &   _BV(1)
    #define SET_OUT_ONEWIRE_DDR_1  DDRC   |=  _BV(1)
    #define SET_IN_ONEWIRE_DDR_1   DDRC   &= ~_BV(1)
    
    
    /* DS18B20 drugi przyłączony do portu  Pc2 AVRa  */
    #define SET_ONEWIRE_PORT_2     PORTC  |=  _BV(2)
    #define CLR_ONEWIRE_PORT_2     PORTC  &= ~_BV(2)
    #define IS_SET_ONEWIRE_PIN_2   PINC   &   _BV(2)
    #define SET_OUT_ONEWIRE_DDR_2  DDRC   |=  _BV(2)
    #define SET_IN_ONEWIRE_DDR_2   DDRC   &= ~_BV(2)
    
    
    
    
    unsigned char ds18b20_ConvertT_1(void);
    unsigned char ds18b20_ConvertT_2(void);
    int ds18b20_Read_1(unsigned char []);
    int ds18b20_Read_2(unsigned char []);
    void OneWireStrong_1(char);
    void OneWireStrong_2(char);
    unsigned char OneWireReset_1(void);
    unsigned char OneWireReset_2(void);
    void OneWireWriteByte_1(unsigned char);
    void OneWireWriteByte_2(unsigned char);
    unsigned char OneWireReadByte_1(void);
    unsigned char OneWireReadByte_2(void);
    
    #endif
    
    [/b]
  • REKLAMA
  • Pomocny post
    #2 8862037
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #3 8865294
    arktik1
    Poziom 27  
    I sprawdź, czy aby na pewno prędkość oscylatora zgadza się z programową.
  • REKLAMA
  • #4 8865702
    norbis15
    Poziom 14  
    Witam, trochę odbiegnę od tematu gdyż sam potrzebuje termometr dwupunktowy na ds-ach i wyświetlaczach LED, jednak nie potrafie pisać programów. Zrobilem termometr na attiny2313 i 3wyświetlaczach LED lecz jednopunktowy. Czy mogłby ktoś przerobić program na ten procesor i aby obsługiwał dwa ds-y w połączeniu 1-wire. Przypuszczam że jest to kwestia zmiany kilku linijek kodu. jeśli tak to zamieszczę schemat mojego urządzenia. Wyświetlacze LED również są multipleksowane u mnie.
  • #5 8865776
    Krokus22
    Poziom 19  
    Witam, rozwiązanie użytkownika Atom1477 z zarzadzaniem przerwaniami cli()/sei() pomogło, teraz pomiar jest bardzo stabilny i aż miło patrzeć, bardzo dziękuję za prostą i fachową pomoc, natomiast początkującemu koledze proponuję artykuł z kursu C dioda dotyczącego 1wire (użyj jego bibliotek), a multipleks napisz sam, opis na stronie kursu wkrętak, bazując na moim kodzie masz już prawie gotowy wsad, powodzenia!
REKLAMA