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

Termostat [C][AVR] - problemy z "wieszaniem się"

misiek1994 08 Wrz 2010 19:13 2268 7
  • #1 8489628
    misiek1994
    Poziom 17  
    Witam! Zrobiłem sobie termostat i wszystko ładnie po podłączałem oraz oprogramowałem. Jest jednak jeden problem: chce sobie zrobić podmenu (ustawianie histerezy). Na początek tworzenia w/w podmenu chciałem sprawdzić, czy są wciśnięta oba przyciski, a nastepnie wyczyścić wyświetlacz i wypisać aktualną temperaturę. Problem jest jednak taki, że wszystko działa, gdy przekaźnik jest wyłączony (sterowanie przez BD649, bramka przez 10k na pin uC; wg. noty prąd pobierany przez przekaźnik niecałe 50mA), natomiast gdy przy włączonym przekaźniku spróbujemy wyczyścić wyśw. i wejść do podmenu to wszystko sie sypie z nieznanego mi bliżej powodu.
    Zamieszczam kod. Może ma ktoś jakiś pomysł?

    Procedury wyświetlacza i temrometru są od autora kursu C na diodzie - abxyz
    /*
       Plik "main.c"
    */
    
    #include <stdio.h>
    #include <avr/io.h>
    #include <util/delay.h>
    #include "hd44780.h"
    #include "ds18b20.h"
    #define SET_PRZ      PORTB |=  _BV(PB7)
    #define CLR_PRZ      PORTB &= ~_BV(PB7)
    
      /* Zmienna przechowuje aktualną wartość temperatury */        
      double temp;
    /* W tablicy będą formowane komunikaty tekstowe
       wysyłane do wyświetlacza */
    char str[7];
    char str2[7];
      double ust = 23;
      double hist= 0;
      char tem[6]="Temp:";
      char zad[8]="Zadana:";
       char test[8]="podmenu";
    int z;
    
    void klawiatura (void) 
    { 
        
       if (!(PIND  &   _BV(PD5)))   //  
       { 
       _delay_ms(70);
             if (!(PIND  &   _BV(PD6)))   // 
       { 
    
         LCD_CLEAR;    
        LCD_LOCATE(0,0);
          /* Wysyła komunikat do wyświetlacza */
           lcd_puts(str);
    	   _delay_ms(100);
     
    	}
    	  ust=ust+1; 
    	  _delay_ms(150);
    	  
       } 
        
       else if (!(PIND  &   _BV(PD6)))   // 
       { 
    		if (!(PIND  &   _BV(PD5)))   // 
       { 
      LCD_CLEAR;    
        LCD_LOCATE(0,0);
          /* Wysyła komunikat do wyświetlacza */
           lcd_puts(str);
    	   _delay_ms(1000);
       }
          ust=ust-1; 
    	  _delay_ms(150);
       }
       else
       {
       	  LCD_CLEAR;
          /* Formułuje komunikat w tablicy 'str' */
           sprintf(str,"%4.1f\xdf""C", temp);
    		sprintf(str2,"%4.1f\xdf""C", ust);
           LCD_LOCATE(0,0);
          /* Wysyła komunikat do wyświetlacza */
           lcd_puts(tem);
    	   LCD_LOCATE(9,0);
    	   lcd_puts(str);
    	   LCD_LOCATE(0,1);
    	   lcd_puts(zad);
    	  LCD_LOCATE(9,1);
    	   lcd_puts(str2);
       }
           
                    for (z=0; z<10 ;z++)   // pauza po przyciśnięciu klawisza 
          { asm ("nop") ;} 
    }
    void start (void)
    {
      /* Czyści  ekran */
      LCD_CLEAR;        
           LCD_LOCATE(0,0);
          /* Wysyła komunikat do wyświetlacza */
           lcd_puts(tem);
    	   LCD_LOCATE(0,1);
    	   lcd_puts(zad);
    }
    void histereza (void)
    {
      LCD_CLEAR;    
        LCD_LOCATE(0,0);
          /* Wysyła komunikat do wyświetlacza */
           lcd_puts(str);
    	   _delay_ms(1000);
    }
    
    int main(void)
    {
    DDRD  = 0x60;
    PORTD = 0x60;
    DDRB  |=  _BV(PB7);
    
    
      /* W tablicy zapisywane będą dane odczytane z układu ds18b20 */
      unsigned char ds18b20_pad[9];
      
      /* Funkcja inicjalizuje wyświetlacz */
      lcd_init();
      /* Włącza wyświetlanie */
      LCD_DISPLAY(LCDDISPLAY);  
        
      
    
    
      while(1)
      {
        /* Funkcja 'ds18b20_ConvertT' wysyła do układu ds18b20 
           polecenie pomiaru */      
         if(ds18b20_ConvertT())
        {
    
          /* Odczyt z układu ds18b20, dane zapisywane są w tablicy ds18b20_pad. 
             Dwie pierwsze pozycje w tablicy to kolejno mniej znaczący bajt i bardziej 
         znaczący bajt wartość zmierzonej temperatury */            
           ds18b20_Read(ds18b20_pad);
              
          /* Składa dwa bajty wyniku pomiaru w całość. Cztery pierwsze bity mniej
             znaczącego bajtu to część ułamkowa wartości temperatury, więc całość
             dzielona jest przez 16 */       
           temp = ((ds18b20_pad[1] << 8) + ds18b20_pad[0]) / 16.0 ;
            if(temp<ust-hist){
    	  CLR_PRZ;
    	  } 
    	  else if(temp>ust+hist){ 
    	  SET_PRZ;	 
    	  }
    
    	   klawiatura();
        }
      }
    }
    
  • #2 8489664
    _Robak_
    Poziom 33  
    Kod na nic się nie zda bez schematu i PCB.
  • #3 8491180
    flapo213
    Poziom 21  
    Witaj,

    No całego kodu nie zamieściłeś.

    Pierwsze co bym sprawdził to funkcję

    
    
    ds18b20_Read(ds18b20_pad);
    
    


    czy przypadkiem nie przekraczasz dozwolonego obszaru.

    Gdybyś zamieścił resztę to może coś by i było.

    pozdrawiam
  • #4 8491266
    tmf
    VIP Zasłużony dla elektroda
    misiek1994 - wątpię, żeby komuś chciało się analizować taki kawałek kodu, tym bardziej, że używasz w nim wielu funkcji o których nic nie wiemy, a one z dużym prawdopodobieństwem mogą być przyczyną twoich problemów. Spróbuj wywalić z programu wszystko co niepotrzebne dla zilustrowania problemu i pokaż tak okrojony kod, ale cały. Zresztą najpewniej przy okazji okaże się, że sam wpadniesz na to co jest nie tak.
  • #5 8491589
    piti___
    Poziom 23  
    temp = ((ds18b20_pad[1] << 8) + ds18b20_pad[0]) / 16.0 ;

    nie jest to rozwiązanie problemu ale wydaje mi się że przesunięcie bitowe na unsigned char da wynik 0.
  • #6 8491613
    gaskoin
    Poziom 38  
    nieprawda

    przesunięcie bitowe "zwróci" liczbę 16 bitową
  • #7 8496597
    misiek1994
    Poziom 17  
    Dobra, olśnienie! Zasilacz nie wydala. Kod jest ok. Nie wiem tylko czemu tak drastycznie spada napięcie na zasilaczu (jeszcze). Dzięki za pomoc :)
  • #8 8526552
    misiek1994
    Poziom 17  
    Jeszcze zostawie krótką notke dla potomnych i zamykam:
    Jeżeli podłączamy przekaźnik do uC i stosujemy zasilacz o małej (lecz teoretycznie) wystarczającej wydajności prądowej niezbędny jest wtedy duży kondensator na zasilaniu, gdyż bez niego efekt jest taki, że po załączeniu przekaźnika następuje duży skok prądu, przez co drastycznie spada napięcie (oczywiście wszystko się dzieje w ułamku sekundy) i gdy procesor ma poniżej jakiegoś krytycznego 3,5V to się resetuje, bądź wiesza. To wszystko. Niby taka pie..oła, a jak się nie ma doświadczenia to trudno na to wpaść :)
    Pdzr misiek
REKLAMA