ADC ve Yazılımsal PWM ile RGB Led Kontrolü

Başlatan Cemre., 19 Haziran 2012, 13:57:42

Cemre.

Yanlız hala problemim var suan sadece set_timer0(?); değeriyle oynuyorum ve en yüksek frekans 53 görebildim 8MHz'de çalışıyorum şu kesmenin mantığını yani o değerle neyi değiştirdiğimi küçük bir örnekle açıklayabilirmisiniz acaba?

serhat1990

Timer0 8 bitlik sayıcıdır dedik.

2^8=256 yapar. Buda 0-255 arasında saymaya yarar.

set_timer0(x)= değeri ile timer'in hangi değerden başlayacağını belirlersin.

Yani sayma x'den başlar. 255'e kadar gider...

fosc=8MHz    osilatörün 8 mhz olduğuna göre fkomut ve tkomut bu şekilde hesaplanır...
Fkomut=8MHz/4=2MHz
Tkomut=1/2MHz=500nS

kesme olusma suresi hesaplama=Tkesme=Tkomut x prescaler degeri x (256 - timer0 degeri )

set_timer(0); dediğine göre.  Kesme süren. = (500x10^-9) X 1 X (256-0)= 128uS çıkıyor.

1/Tkesme=frekans olacağına göre...

CIKIS FREKANSI=7812.5Hz=7.81KHz ' lik bir sinyal görmen gerekli...

Yanlışlık yoktur umarım  . Kafam Çok dağınık. Linki incelersen detaylı bir anlatım mevcut..

http://www.teknobakis.com/ccs-c-ile-pic-programlama-pic-timer-modulleri-ve-kullanimi-1

Kolay gelsin...

justice_for_all

tabi bu senin timer frekansın pwm frekansını bulabılmek ıcinde timer frekansı/255 yapman gerek.
Deneyip de başaramayanları değil, yalnızca denemeye bile kalkışmayanları yargıla.   Gökhan Arslanbay

Cemre.

Çok teşekkürler ilgilendiğiniz için :) biraz daha uğraşayım bakalım :)

serhat1990

Kolay gelsin .  :)

Umarım sorun çözülür bu arada kullandığın

8MHZ osilatör demişsin ama yazılımda 4mhz ayarlamıssın..

#use delay(clock=4000000)  ; olarak ayarlamıssın ...

Cemre.

#20
O ilk yazılım olduğu için, daha sonra değişiklik yaptım tabi ki :)

Şu an farklı bi devre ve yeniden yazılmış kodlarla çalışıyorum ancak frekansım 40ın üzerine çıkamıyor :/

#include <16F88.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC                    //Internal RC Osc
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled
#FUSES NOIESO                   //Internal External Switch Over mode disabled

#use delay(clock=8000000)
int i=0;
int k=0;

#INT_TIMER0
void timer0_kesmesi(){
   set_timer0(100);
   i++;
   if(i<=k)output_high(PIN_B7);
   if(i>k)output_low(PIN_B7);
   delay_us(10);
   if(i>=255){i=0;};
}
void main()
{

   setup_adc_ports(sAN0|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_CCP1(CCP_OFF);
   setup_vref(FALSE);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   set_tris_b(0x00);
   output_b(0x00);
   
   while(1){
    set_adc_channel(0);
    delay_us(30);
    k = read_adc();
   }
}


[SPICE] transient GMIN stepping at time=******* gibi binlerce hata veriyor her saniye ISIS 
*  set_timer0(0); yaptığımda düzeldi :)

justice_for_all

#21
timer kesmesindeki delayı kaldırın biraz daha hızlanacaktır.

ayrıca internal osc de 8 mhz secmek için main kısmında asagıdaki kod satırı olmalıdır.

setup_oscillator(OSC_8MHZ|OSC_INTRC);
Deneyip de başaramayanları değil, yalnızca denemeye bile kalkışmayanları yargıla.   Gökhan Arslanbay

Cemre.

#22
Frekansım 27den 28e çıktı  :P

Ben kHz'lere ihtiyacım olduğunda ne yapacağım :D  :o

justice_for_all

en son dediğimide denedinizmi frekans çok düşük ben 100 herze cıkmıstım zaten khz isiyosan timer ile biraz zor  o iş.
Deneyip de başaramayanları değil, yalnızca denemeye bile kalkışmayanları yargıla.   Gökhan Arslanbay

Cemre.

#justice_for_all > yinede hiç bir değişiklik yok bir yerde hata mı yapıyorum istediğim sadece kırpışma yerine şiddeti azalan artan ışıklar istiyorum ve bunun içinde ilk sayfada hocamızın belittiği 70Hz sınırını aşmak istiyorum :/

#justice_for_all > Evet, onu da ekledim :)

justice_for_all

#include <10F206.h>

#FUSES NOWDT                 	//No Watch Dog Timer
#FUSES NOMCLR                	//Master Clear pin used for I/O

#use delay(clock=4000000)

#byte osc_cal=0x05

#define r		PIN_B0
#define arti	PIN_B1
#define eksi	PIN_B2


unsigned int8 duty1=100,periyot=0,temp=0;

void pwm(void)
{
   #asm 
   	decfsz periyot
   	goto LABEL1
   	MOVLW	255
   	MOVWF 	periyot
   
   	BSF		0x06,0
	BSF		0x0D,0
	 
 LABEL1	:

       MOVF 	duty1,W
       SUBWF	periyot,W
       BTFSS	0x3,2
       GOTO	LABEL2
       BCF		0x06,0
       BCF		0x3,2
       
 LABEL2:
 	
 	MOVLW	240
   	MOVWF	0x01
 

   #endasm
}
void main()
{
   osc_cal=0b00000000;
   #asm
   MOVLW 0xC0
   OPTION
   MOVLW 0
   MOVWF 0x07
   #endasm
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1|RTCC_8_bit);		//256 us overflow
   set_tris_b(0x06);
   
   set_timer0(0);
  
   while(true)
   {

      temp=get_timer0();
      if(temp>=10)
      {
        temp=0;
        pwm();
      }
  }
}


ben yukarıda yaptıgım programda 100 hz pwm yapmıştım.senin programına benziyor rgb led içinde yapmıstım ama yanımda değil suan onuda gonderirim aksam.
Deneyip de başaramayanları değil, yalnızca denemeye bile kalkışmayanları yargıla.   Gökhan Arslanbay

serhat1990

Çok zor birşey değil ya . Gözden kaçan birşey var heralde. Timer kullanmadan ana fonksiyon içinde bir değişken saydır. Bu değişkenin adc degerini geçince pinlerin durumunu tersle. Her sayma işlemi bitince ( yani periyodunu sayma değerine göre ayarlayacaksın ) sayıcı değerini sıfırlarsın...

Cemre.

#27
#serhat1990 > sanırım demek istediğiniz şöyle birşey

#include <16F88.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC                    //Internal RC Osc
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled
#FUSES NOIESO                   //Internal External Switch Over mode disabled

#use delay(clock=8000000)
int i=0;
int k=0;

#INT_TIMER0
void timer0_kesmesi(){
   set_timer0(110);
   i++;
   if(i<=k)output_high(PIN_B7);
   if(i>k)output_low(PIN_B7);
   if(i>=145){i=0;};
}
void main()
{

   setup_adc_ports(sAN0|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_oscillator(OSC_8MHZ|OSC_INTRC);
   setup_CCP1(CCP_OFF);
   setup_vref(FALSE);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   set_tris_b(0x00);
   output_b(0x00);
   
   while(1){
    set_adc_channel(0);
    delay_us(30);
    k = read_adc();
   }
}


Bununla 74Hz'deyim, ancak şimdi küçük bir problemim var, i değişkenimi 145'te sıfırladığım için ondan sonraki ADC değerlerimi yani POT'da neredeyse yarıdan sonrasını okuyamıyorum, tam yanmaya dönüşüyor. Bunu da sanırım ADC referans voltajlarımla oynayarak düzelteceğim ama ben bunun dışında bir çözüm arıyorum çünkü devreyi en sade haliyle bitirmek benim için en iyisi, yazılımsal olarak bir çözümü bulamaz mıyız?


#serhat1990 > İstediğim şey şu Timer olayını öğrenmek, evet bunu for döngüsüyle dahi basit bir şekilde yapabileceğimi sanıyorum, ama Timer :)))

justice_for_all

timer a 110 değilde 200 yukleyebilirsin i yi ise 255 yapabilirsin veya 512 veya 1024 adc 10 bitlik oldugu için en hassas ayar için i 1024 olması gerekir.veya adc yi 8 bit olarak ayarlarsın iyi ise 255 e kadar arttırırsın.
Deneyip de başaramayanları değil, yalnızca denemeye bile kalkışmayanları yargıla.   Gökhan Arslanbay

Cemre.

Evet teşekkürler sorunumu çözecek şey buydu sanırım :) Şimdi bunu RGB devrem için yeniden yazmalıyım :)