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

[Atmega16][C]program do obslugi ściemniacza

mby 03 Kwi 2010 15:33 1597 6
REKLAMA
  • #1 7915837
    mby
    Poziom 10  
    Witam! Napisalem program do obslugi ściemniacza na atmega16. Korzystamy z portu d. PD5 to pin wyjściowy sterujący triakiem. Impuls podany na PD3 lub PD4
    zwieksza lub zmniejsza wartość zmiennej 'sel' regulując sterowaniem fazowym.
    PD2(INT0) tu pojawia sie przerwanie zboczem opadajacym od ukladu detekcji zera.

    Program ten prawie w ogole nie dziala. Napisalem go dwa razy, śledzilem dzialania krok po kroku i nic. gdy ustawie domyslna wartość świecenia na jakas pośrodku(sel = 5) żarówka dalej świeci pelna para! gdy podaje impuls na na PD4 PD5 żarówka w ogole przestaje świecic. Prosze o jakies sugestie, bo jestem zdesperowany.

    
    
    #include<avr/io.h>
    #include<avr/interrupt.h> 
    #define F_CPU 12000000
    #include<util/delay.h>
    #include <stdint.h> 
    
    
    #define xISC01 1 << 1
    #define xINT0 1 << 6
    #define xCS11 1 << 1
    #define xOCIE1A 1 << 4
    #define xOCIE1B 1 << 3
    
    #define MAX_SEL 8
    #define CYCLES_TO_WAIT 0xff
    #define xSET_OCR1B 15000
    
    uint16_t del[MAX_SEL] = {11262, 10372, 9485, 8567, 7575, 6432, 4944, 3847};
    char sel = 5; // wybor jasnosci 
    int count = 0;
    
    void pulse(void){
    	
    	PORTD |= 1 << 5;
    	_delay_us(10);
    	PORTD &= ~(1 << 5);
    
    }
    
    void set_I(char en){
    	if(en == 1){
    		SREG |= 1 << 7;
    	} else {
    		SREG &= ~(1 << 7);
    	}
    }
    
    void start_TCNT1(char en){
    	if(en == 1){
    		TCCR1B |= xCS11;
    	} else {
    		TCCR1B &= ~xCS11;
    	}
    }
    
    void set_OCIE1A(char en){
    
    	if(en == 1){
    		TIMSK |= OCIE1A;
    		}else{
    		TIMSK &= ~OCIE1A;
    		}
    
    }
    
    void set_OCIE1B(char en){
    
    	if(en == 1){
    		TIMSK |= xOCIE1B;
    		}else{
    		TIMSK &= ~xOCIE1B;
    		}
    
    }
    
    
    void port_config(void){
    	//konfiguracja portu D
    
    	DDRD = 0x00; // ustawienie wszystkich portow jako wejsciowych
    	DDRD |= 1 << 5; // konfiguracja 5. bitu portu na wyjściowy
    
    	PORTD = 0x00; // konfiguracja wyjsc na 0 i wylaczenie podciagania na wejsciach
    	PORTD |= 1 << 2 || 1 << 3 || 1 << 4; // podciąganie na portach  wejściowym
    
    }
    
    
    void ext_interrupt_config(void){
    	
    	MCUCR = 0;
    	MCUCR |= xISC01; // wywolanie przerwania zboczem opadajacym
    
    	GICR = 0;
    	GICR |= xINT0; // interrupt enable dla int0
    
    }
    
    void counter_config(void){
    
    	OCR1B = xSET_OCR1B; // ustawiamy ilosc impulsow odpowiadajacych T/2
    
    	TIMSK = 0;
    
    	set_OCIE1A(0);
    	set_OCIE1B(1);// aktywacja przerwań od timera - compare match
    
    	TCCR1B = 0;
    	
    }
    
    
    ISR(INT0_vect){
    
    
    	// sprawdzamy czy nie zmienic jasnosci - caly if
    	if(count == CYCLES_TO_WAIT){
    		if(!((PORTD & (1 << 3)) == (1 << 3)) && (sel != MAX_SEL - 1)){
    		++sel;
    		} else if(!((PORTD & (1 << 4)) == (1 << 4)) && (sel != 0)) {
    		sel--;
    		}
    		
    		OCR1A = del[sel]; // zmiana jasnosci swiecenia po modyfikacji sel				
    		count = 0;
    	}else{
    	PORTB = count;
    	++count;
    	} 
    	// koniec sprawdzenia
    
    	TCNT1 = 0; // wyzerowanie timera
    	set_OCIE1A(1);
    	//set_I(0); // wylaczam absluge przerwan aby uruchomic timer1
    	start_TCNT1(1);
    	//set_I(1);*/
    }
    
    ISR(TIMER1_COMPA_vect){
    	start_TCNT1(0);
    	pulse();
    	set_OCIE1A(0);
    	set_OCIE1B(1);
    	TCNT1 = 0;
    	start_TCNT1(1);
    	}
    
    ISR(TIMER1_COMPB_vect){
    	start_TCNT1(0);
    	pulse();
    	}
    
    int main(void){
    
    SREG = 0; // zabezpieczenie przed nadejsciem przerwania przed konfiguracja
    OCR1A = del[sel];
    port_config();
    ext_interrupt_config();
    counter_config();
    SREG = 1 << 7; // ruszamy z praca!
    
    label:
    while(1){
    
    }
    goto label;
    }
    
    
  • REKLAMA
  • #2 7916842
    archanoid
    Poziom 26  
    Witam. Kolego może jakiś schemat , to troszkę rozjaśni problem . Jak sterujesz triakiem przez optotriak .
  • REKLAMA
  • #3 7917896
    mby
    Poziom 10  
    tak, steruje triakiem przez optotriak. Na INT0 podawane jest 0 gdy napiecie sieci jest dodatnie a 1 gdy napiecie sieci jest ujemne(optotranzystor podpiety pod INT0 - wlączony rezystor podciągający). W zasadzie to tyle. Część analogowa na 100% działa, przetestowalem.
  • REKLAMA
  • #4 7919724
    archanoid
    Poziom 26  
    Witam. Do sterowania fazowego należy użyć optotriaka bez detektora zera czyli np: MOC3023M . Kolejną rzeczą to przerwanie INT0 . W twoim przypadku powinno być wyzwalane nie opadającym zboczem a zmianą stanu czyli bit ISC00 = 1. Jeśli zasilasz układ z klasycznego zasilacza transformatorowego czyli trafko mostek kondensatory i stabilizator to lepiej zrobić układ wyzwalania krótkim impulsem przy każdym przejściu napięcia przez zero.
    [Atmega16][C]program do obslugi ściemniacza
  • #5 7922574
    mby
    Poziom 10  
    faktycznie - jedyny błąd to było że przerwanie bylo uruchamiane zboczem a nie poziomem. Działający kod zamieszczam poniżej, może komuś się przyda ;)

    
    #include<avr/io.h>
    #include<avr/interrupt.h>
    #include<stdint.h> 
    
    #define xISC01 1 << 0
    #define xINT0 1 << 6
    #define xCS11 1 << 1
    #define xOCIE1A 1 << 4
    
    
    uint16_t del[8] = {11262, 10372, 9485, 8567, 7575, 6432, 4944, 3847};
    
    int count;
    int sel;
    
    void pulse(void){
    	PORTD |= 1 << 5;
    	int i = 0;
    	while(i++ < 2){
    	}
    	PORTD &= ~(1 << 5);
    }
    
    void set_I(char en){
    	if(en == 1){
    		SREG |= 1 << 7;
    	} else {
    		SREG &= ~(1 << 7);
    	}
    }
    
    void start_TCNT1(char en){
    	if(en == 1){
    		TCCR1B |= xCS11;
    	} else {
    		TCCR1B &= ~xCS11;
    	}
    }
    
    void set_OCIE1A(char en){
    	if(en == 1){
    		TIMSK |= xOCIE1A;
    		}else{
    		TIMSK &= ~xOCIE1A;
    		}
    }
    
    
    void port_config(void){
    	//konfiguracja portu D
    	DDRD |= 1 << 5; // konfiguracja 5. bitu portu na wyjściowy
    	PORTD |= 1 << 3 | 1 << 4;
    }
    
    
    void ext_interrupt_config(void){
    	MCUCR |= xISC01; // wywolanie przerwania zboczem opadajacym
    	GICR |= xINT0; // interrupt enable dla int0
    }
    
    void counter_config(void){
    	OCR1A = 7500; // dowolna wartość
    	set_OCIE1A(1);
    }
    
    
    ISR(INT0_vect){
    
    	if(count == 0xff){
    		if(!((PIND & (1 << 3)) == (1 << 3)) && (sel != 7)){
    		++sel;
    		}
    		
    		if(!((PIND & (1 << 4)) == (1 << 4)) && (sel != 0)) {
    		sel--;
    		}
    		
    		OCR1A = del[sel]; // zmiana jasnosci swiecenia po modyfikacji sel				
    		count = 0;
    	}else{
    	++count;
    	} 
    	
    	TCNT1 = 0; // wyzerowanie timera
    	start_TCNT1(1);
    }
    
    ISR(TIMER1_COMPA_vect){
    	start_TCNT1(0);
    	pulse();
    	}
    
    
    int main(void){
    
    set_I(0); // zabezpieczenie przed nadejsciem przerwania przed konfiguracja
    port_config();
    ext_interrupt_config();
    counter_config();
    
    count = 0;
    sel = 5;
    
    set_I(1); // ruszamy z praca!
    
    label:
    while(1){
    }
    goto label;
    }
    
    
    


    Mam zamiar do tego projektu dodać obsługe dwóch dodatkowych lamp, obsługe pilota z kode rc5 oraz wyjświetlanie na wyświetlaczach 7segmentowych informacji o obsługiwanej lampie i 'procecie' świecenia.

    I moje pytanie: czy obsługe pilota i wyświetlanie zrobić na tym samym mikrokontrolerze czy mam użyć drugiego?
  • REKLAMA
  • #6 7923589
    archanoid
    Poziom 26  
    Witam. Odnośnie przerwania nic nie zmieniłeś po jakim warunku ma zostać zgłoszone przerwanie . Bez schematu sam kod jest tylko połowicznie coś wart. Można w takim prostym przypadku odtworzyć schemat na podstawie kodu , ale dla kogoś kto będzie chciał zbudować takie urządzenie z twoim kodem to tylko dodatkowe utrudnienie.
REKLAMA