RGB Led ve PWM Nasıl?

Başlatan kostebek, 11 Nisan 2008, 10:11:14

kostebek

Merhaba arkadaşlar 16F628A nın tek çıkış PWM modunu RGB lede veriyorum. Sırayla renkleri tetikleyerek de farklı PWM lerde farklı renk kombinasyonları moluşturabiliyorum. Ama amacım böyle kendi kendine bir şov yapmak

http://www.youtube.com/watch?v=6y15_S88e3I&feature=related

adresteki gibi. Bir türlü çözemedim nasıl olduğunu.. Benim kodlarım şöyle

#include <16F628.H>
#device *=16
#fuses INTRC,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#include <lcd.c>
#define pin_kir       PIN_A0   // kirmizi ledi iletime sokar
#define pin_mav       PIN_A1 // mavi ledi iletime sokar
#define pin_yes       PIN_A2  // yesil ledi iletime sokar


int   k,m,y;         


void main()
   {
   setup_ccp1(CCP_PWM);  // CCP1 birimi PWM çıkışı için ayarlandı


   setup_timer_2(T2_DIV_BY_16,170,1); // Timer2 ayarları yapılıyor

   set_pwm1_duty(0); // PWM1 çıkışı görev saykılı belirleniyor

   lcd_init();
   k=15;
   m=56;
   y=64;
   while(1)
   { 

   k=k+1;
   y=y+2;
   m=m+3;
   //LCD ye o anki K Y M değerlerini yaz
   printf(lcd_putc,"\f K=%u M=%u Y=%u", k,m,y);

   output_high(pin_kir);
   set_pwm1_duty(k);
   delay_ms(40);
   output_low(pin_kir);

   output_high(pin_mav);
   set_pwm1_duty(m);
   delay_ms(40);
   output_low(pin_mav);
   
   output_high(pin_yes);
   set_pwm1_duty(y);
   delay_ms(40);
   output_low(pin_yes);
      if(k>160){
   k=7;
   }
      if(y>160){
   y=12;
   }
      if(m>160){
   m=2;
   }
   
   
   
   }
 



}

Andromeda

yöntemin ilginç.şöyle yapsan;
ortak ucu artı veya eksiye bağla.diğer uçlara pwm ver.
bunu yazılım ile yapman gerekecek
" Tanrı, iradesini hakim kılmak için yeryüzündeki iyi insanları kullanır, yeryüzündeki kötü insanlar ise kendi iradelerini hakim kılmak için Tanrı'yı kullanırlar." ..." Tanrı'dan mesaj gelmiyor, biz Tanrı'ya mesaj gönderiyoruz"

kostebek

Merhaba arkadaşım sağol yanıtın için yalnız şöyle bir durum var. Elimdeki RGB ortak Anodlu bir led. Bütün bacakları NPN transistörle toprağa çektim. ortak Anoda ise PWM çıkışını verdim. Ben hangi transistörü anahtarlarsam o iletimi girip mevcut rengi yakıyor. Aslında yöntem böyle donanım olarak ama işte yazılım algoritmasını kuramadım  :D


M_B

umarım aşagıdakı kod işine yarar.
kolay gelsın.
M_B

#include <12F675.h> 
#use delay (clock=4000000) 
#fuses INTRC_IO,noWDT,PUT,NOBROWNOUT,noPROTECT,NOPUT,NOCPD,MCLR 

#define    led1      PIN_A0//yes  led 220R +V 
#define    led2      PIN_A1//mavi led 220R +V 
#define    led3      PIN_A2//kirm led 220R +V 

// #ROM 0x3ff = {0x3480} 

BYTE CONST TABLE [120]= { 
                250,80,0,220,70,0,200,30,0, 
                180,0,30,150,0,60,120,0,80, 
                100,0,120,80,0,150,60,0,180, 
                30,0,200,20,0,230,0,20,250, 
                0,40,220,0,60,200,0,80,170, 
                0,100,150,0,120,120,00,150,100, 
                0,180,80,0,200,60,0,220,40, 
                0,250,20,10,220,0,20,200,0, 
                30,200,0,40,170,0,50,10,0, 
                250,0,0,220,0,0,200,0,0, 
                180,0,0,150,0,0,120,0,0, 
                0,0,100,0,0,120,0,0,140, 
                0,0,180,0,0,200,0,20,250, 
                0,40,220, 
            }; 
//////////////////////////////////////////////////////////////////////// 
void main() { 

int16 titrval, dampval; 
int led1val,led2val,led3val, deger,tablsay,lighthed1,lighthed2,lighthed3; 
SET_TRIS_A   (0b00001000); 
SETUP_TIMER_1(T1_DISABLED ); 
setup_comparator(NC_NC_NC_NC); 
setup_ADC_ports(NO_ANALOGS); 

   tablsay = 0; 
///////////////////////////////////////////////////////////////////////// 
while(1){ 

deger++; 
titrval++; 
dampval++; 
////////////////////////////////////// 
if (titrval == 2000){   //tablodan set say al 
   titrval = 0; 
   if (tablsay >= 98) tablsay = 0; 
   lighthed1 = table [tablsay]; 
   lighthed2 = table [tablsay+1]; 
   lighthed3 = table [tablsay+2]; 
   tablsay+=3;} 
/////////////////////////////////////// 
if (dampval ==600){//soft 
   dampval = 0; 
   if (led1val < lighthed1) led1val++; 
   if (led1val > lighthed1) led1val--; 
   if (led2val < lighthed2) led2val++; 
   if (led2val > lighthed2) led2val--; 
   if (led3val < lighthed3) led3val++; 
   if (led3val > lighthed3) led3val--;} 
//////////////////////////////////////// 
if( deger < led1val ) 
   { 
   output_low(led1); 
   } 
else 
   { 
   output_high(led1); 
   } 

if( deger < led2val ) 
   { 
   output_low(led2); 
   } 
else 
   { 
   output_high(led2); 
   } 

if( deger < led3val ) 
   { 
   output_low(led3); 
   } 
else 
   { 
   output_high(led3); 
   } 
} 

} 
/////////////////////////////////////////


Not: Program alıntıdır.  Nerden aldıgımı hatırlayamadım.
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

picusta

CCP'nin interrupt'unu kullansan, PWM'in reload register'ini ve bu isi tamamen interruptla yapsan güzel olmaz mi?
Ana program LCD'ye birseyler yazmak için veya renk dizilerini seri porttan almak için kullanabilirsin.

erkan614

@kösbebek mesajında 1 adet pwm çıkışını ortak anoda bağladığını yazmışsın bu bağlantı şekli ile renk aralıklarını eldeedemezsin.

3 adet pwm herbir rennk için olmalı ki bu renklere uyguluycağın farklı duty lerle ara renkleri elde edebilesin.

3 pwm için 18f1330 da donanımsal olarak vardı ama gerek yok arkadaşların de dediği gibi interrupt ile yapabilirsin.

ben 12f675 ile yapmıştım assembly dilinde c ile sen çok daha rahat yaparsın

aliveli

aşağıdaki program http://www.ccsinfo.com/forum/viewtopic.php?t=30139 adresinden alıntıdır
//**************************************************************************************************
// Andre Broodryk
// Led fader
// 2006/07
//**************************************************************************************************

#include <16F917>
#fuses INTRC_IO,NOPROTECT,NOWDT,PUT
#use delay(clock=8000000)
#use standard_io(d)
#define preload 65458
#define red pin_d0
#define green pin_d1
#define blue pin_d2

//**************************************************************************************************
//Global variables
//**************************************************************************************************

int red_duty;
int green_duty;
int blue_duty;
int Intcount;

//**************************************************************************************************
//100Hz pwm (interupt at 25.8kHz
//**************************************************************************************************

#INT_TIMER1
void timer_irq()
{
    set_timer1(preload);
   
   if (Intcount < 255)
    {
      if (Intcount == red_duty)
       {
         output_low(red);
       }   
      if (Intcount == green_duty)
       {
         output_low(green);
       }   
      if (Intcount == blue_duty)
       {
         output_low(blue);
       }   
    }
   
   else if(Intcount == 255)
    {
      Intcount = 0;
      output_high(red);
      output_high(green);
      output_high(blue);   
    }   
    Intcount++;
}


//**************************************************************************************************
// Main Program
//**************************************************************************************************

void main()
{
   setup_oscillator(OSC_8MHZ);
    setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
    enable_interrupts(INT_TIMER1);
    enable_interrupts(GLOBAL);
   red_duty = 63;
   green_duty = 1;
   blue_duty = 250;
   Intcount = 0;

   for (;;)
   {

      
   }
}


Burada kodu yapan kişi tam olarak senin yapmaya çalıştığını gerçekleştirmiş.
timer1 ile 25.8kHz'de gerçekleşen interrupt sayesinde 256 adımlık 100Hz PWM sinyali üretmiş
for döngüsü içerinde yapacağın kontrol ve güncelleme ile red_duty, green_duty, blue_duty değerlerini değiştirerek çok çeşitli renkleri elde edebilirsin.

picusta

Bence arkadas gayet ekonomik bir sekilde 3 PWM yapmis.
PWM oranlari %0 ila %33 arasinda degisebiliyor (Led basina PWM frekansi PWM'nin 3'te biri). PWM pulslari 3 led için senkron değil.

kostebek

Alıntı yapılan: "M_B"umarım aşagıdakı kod işine yarar.
kolay gelsın.
M_B

#include <12F675.h> 
#use delay (clock=4000000) 
#fuses INTRC_IO,noWDT,PUT,NOBROWNOUT,noPROTECT,NOPUT,NOCPD,MCLR 

#define    led1      PIN_A0//yes  led 220R +V 
#define    led2      PIN_A1//mavi led 220R +V 
#define    led3      PIN_A2//kirm led 220R +V 

// #ROM 0x3ff = {0x3480} 

BYTE CONST TABLE [120]= { 
                250,80,0,220,70,0,200,30,0, 
                180,0,30,150,0,60,120,0,80, 
                100,0,120,80,0,150,60,0,180, 
                30,0,200,20,0,230,0,20,250, 
                0,40,220,0,60,200,0,80,170, 
                0,100,150,0,120,120,00,150,100, 
                0,180,80,0,200,60,0,220,40, 
                0,250,20,10,220,0,20,200,0, 
                30,200,0,40,170,0,50,10,0, 
                250,0,0,220,0,0,200,0,0, 
                180,0,0,150,0,0,120,0,0, 
                0,0,100,0,0,120,0,0,140, 
                0,0,180,0,0,200,0,20,250, 
                0,40,220, 
            }; 
//////////////////////////////////////////////////////////////////////// 
void main() { 

int16 titrval, dampval; 
int led1val,led2val,led3val, deger,tablsay,lighthed1,lighthed2,lighthed3; 
SET_TRIS_A   (0b00001000); 
SETUP_TIMER_1(T1_DISABLED ); 
setup_comparator(NC_NC_NC_NC); 
setup_ADC_ports(NO_ANALOGS); 

   tablsay = 0; 
///////////////////////////////////////////////////////////////////////// 
while(1){ 

deger++; 
titrval++; 
dampval++; 
////////////////////////////////////// 
if (titrval == 2000){   //tablodan set say al 
   titrval = 0; 
   if (tablsay >= 98) tablsay = 0; 
   lighthed1 = table [tablsay]; 
   lighthed2 = table [tablsay+1]; 
   lighthed3 = table [tablsay+2]; 
   tablsay+=3;} 
/////////////////////////////////////// 
if (dampval ==600){//soft 
   dampval = 0; 
   if (led1val < lighthed1) led1val++; 
   if (led1val > lighthed1) led1val--; 
   if (led2val < lighthed2) led2val++; 
   if (led2val > lighthed2) led2val--; 
   if (led3val < lighthed3) led3val++; 
   if (led3val > lighthed3) led3val--;} 
//////////////////////////////////////// 
if( deger < led1val ) 
   { 
   output_low(led1); 
   } 
else 
   { 
   output_high(led1); 
   } 

if( deger < led2val ) 
   { 
   output_low(led2); 
   } 
else 
   { 
   output_high(led2); 
   } 

if( deger < led3val ) 
   { 
   output_low(led3); 
   } 
else 
   { 
   output_high(led3); 
   } 
} 

} 
/////////////////////////////////////////


Not: Program alıntıdır.  Nerden aldıgımı hatırlayamadım.


M_B Senin verdiğinin denedim gayet güzel çalışıyor. Yalnız renklerde belirgin bir geçiş yok. Onu nasıl ayarlayabiliriz. Mesela renkler hiçbir zaman sırıflanmıyor. Sürekli bir yeşilimsi ya da mavimsi veya karışık bir ton var ortada ?

aslan_korhan

Videodaki renkler için ( Gökkuşağı ) ayni anda 3 adet PWM gerekmiyor.
İlk önce kırmızıyı 0'dan 255'e kadar PWM olarak arttırırsın. 255'e ulaştığında kırmızı çıkışı direkt +5V yap. Sonrada yeşili 0'dan 255'e arttır ve yine yeşili +5V yap. Bundan sonrada kırmızıyı 255'den 0'a doğru azalt. Bu şekilde yaparsan tam istediğin renkler çıkar ve sadece 1 hardware PWM kullanmış olursun. Yani PIC12F675 ile de çok kolaylıkla ve dahili oscilatörünlede hiç titreme yapmadan çalışır.

http://www.youtube.com/watch?v=5ZrE5rY-f5I

Buda bahsini ettiğim mantıkla yaptığım ve 12F675 kullandığım bir örnek...
Dünyada 10 çeşit insan vardır. Binary bilen ve bilmeyenler.

kostebek

Alıntı yapılan: "aslan_korhan"Videodaki renkler için ( Gökkuşağı ) ayni anda 3 adet PWM gerekmiyor.
İlk önce kırmızıyı 0'dan 255'e kadar PWM olarak arttırırsın. 255'e ulaştığında kırmızı çıkışı direkt +5V yap. Sonrada yeşili 0'dan 255'e arttır ve yine yeşili +5V yap. Bundan sonrada kırmızıyı 255'den 0'a doğru azalt. Bu şekilde yaparsan tam istediğin renkler çıkar ve sadece 1 hardware PWM kullanmış olursun. Yani PIC12F675 ile de çok kolaylıkla ve dahili oscilatörünlede hiç titreme yapmadan çalışır.

http://www.youtube.com/watch?v=5ZrE5rY-f5I

Buda bahsini ettiğim mantıkla yaptığım ve 12F675 kullandığım bir örnek...

Mantığı anlattığınız için teşekkür ederim. Örnek video ya da baktım. Gerçekten çok hoş olmuş :).

Yalnız sorum şu Mesela KIRMIZI yı 255'e kadar artır sonra +5V yapıp yeşili 255'e kadar artır diyorsunuz ya. O sırada işte Kırmızı da yeşille beraber artıyor. Ortak Anodlu bir kılıftalar ya 3 led de.

Siz de bunu mu kastediyordunuz. ?

aslan_korhan

Evet, 2 Renk ayni anda yanacak.
Örneğin Kırmızı ve Yeşil ayni anda yanarsa Sarı rengi çıkar.
Kırmızı, Yeşil ve Mavi ayni anda yanarsa beyaz renk elde edersin.
Bu şekilde binlerce renk karışımı elde edersin.
Bir TV'nin tüpünü yakından incelersen sadece 3 ana renkten oluştuğunu görebilirsin. LED olayıda ayni bu mantık...
Dünyada 10 çeşit insan vardır. Binary bilen ve bilmeyenler.

kostebek

Alıntı yapılan: "aslan_korhan"Evet, 2 Renk ayni anda yanacak.
Örneğin Kırmızı ve Yeşil ayni anda yanarsa Sarı rengi çıkar.
Kırmızı, Yeşil ve Mavi ayni anda yanarsa beyaz renk elde edersin.
Bu şekilde binlerce renk karışımı elde edersin.
Bir TV'nin tüpünü yakından incelersen sadece 3 ana renkten oluştuğunu görebilirsin. LED olayıda ayni bu mantık...

Ben şöyle birşeyler yaptım da çalıştıramadım. Rica etsem sizin kodlarınızı görebilirmiyim ?

//**************************************************************************************************
// RGB Led 
// 2008/05/02
//**************************************************************************************************
#include <16F628.H>
#device *=16
#fuses INTRC,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#define red pin_a0
#define green pin_a1
#define blue pin_a2 


int k;
int m;
int y;

 


void main()
   {
   setup_ccp1(CCP_PWM);  // CCP1 birimi PWM çıkışı için ayarlandı
   setup_timer_2(T2_DIV_BY_16,255,1); // Timer2 ayarları yapılıyor
   set_pwm1_duty(0); // PWM1 çıkışı görev saykılı belirleniyor
   lcd_init();

   k = 0;
   m = 0;
   y = 0;
   
   while(1)
   {
  
   //******************1.parça*******************************//
   output_low(green); //iki ledin çıkışını temizle 
   output_low(red);
   output_high(blue);
   for(k=0;k<255;k++){
   set_pwm1_duty(k);
   delay_ms(20);
   }
   //********************************************************//
   //******************2.parça*******************************//
   output_high(green); //iki ledin çıkışını temizle 
   output_low(red);
   output_high(blue);
   for(m=0;m<255;m++){
   set_pwm1_duty(m);
   delay_ms(20);
   }
   //********************************************************//

   //******************2.parça*******************************//
   output_high(green); //iki ledin çıkışını temizle 
   output_high(red);
   output_high(blue);
   for(y=255;y<1;y--){
   set_pwm1_duty(y);
   delay_ms(20);
   }
   //********************************************************//
   }

   
   
   
   }

aslan_korhan

Ben maalesef C'den anlamıyorum. Pic Basic için yazmıştım.
Hem benim örnekte hardware PWM kullanmamıştım...

Dünyada 10 çeşit insan vardır. Binary bilen ve bilmeyenler.

kostebek

#include <16F628.H>
#use delay (clock=4000000)
#fuses INTRC_IO,noWDT,PUT,NOBROWNOUT,noPROTECT,NOPUT,NOCPD,MCLR
#define    led1      PIN_A0//yes  led 220R +V
#define    led2      PIN_A1//mavi led 220R +V
#define    led3      PIN_A3//kirm led 220R +V
#include <lcd.c>
#use fast_io(A)
#ROM 0x3ff = {0x3480}


BYTE CONST TABLE [120]= {
                250,80,0,220,70,0,200,30,0,
                180,0,30,150,0,60,120,0,80,
                100,0,120,80,0,150,60,0,180,
                30,0,200,20,0,230,0,20,250,
                0,40,220,0,60,200,0,80,170,
                0,100,150,0,120,120,00,150,100,
                0,180,80,0,200,60,0,220,40,
                0,250,20,10,220,0,20,200,0,
                30,200,0,40,170,0,50,10,0,
                250,0,0,220,0,0,200,0,0,
                180,0,0,150,0,0,120,0,0,
                0,0,100,0,0,120,0,0,140,
                0,0,180,0,0,200,0,20,250,
                0,40,220,
            };
////////////////////////////////////////////////////////////////////////
void main() {

int16 titrval, dampval;
int led1val,led2val,led3val, deger,tablsay,lighthed1,lighthed2,lighthed3;
SET_TRIS_A( 0x00 );
SETUP_TIMER_1(T1_DISABLED );
lcd_init();
tablsay = 0;

//!printf(lcd_putc,"\fYukleniyor", );
//!delay_ms(400);
//!printf(lcd_putc,"\fGosteri\nBasladi",);
//!delay_ms(600);
/////////////////////////////////////////////////////////////////////////
while(1){

deger++;
titrval++;
dampval++;
//////////////////////////////////////
if (titrval == 2000){   //tablodan set say al
   titrval = 0;
   if (tablsay >= 98) tablsay = 0;
   lighthed1 = table [tablsay];
   lighthed2 = table [tablsay+1];
   lighthed3 = table [tablsay+2];
   tablsay+=3;}
///////////////////////////////////////
if (dampval ==600){//soft
   dampval = 0;
   if (led1val < lighthed1) led1val++;
   if (led1val > lighthed1) led1val--;
   if (led2val < lighthed2) led2val++;
   if (led2val > lighthed2) led2val--;
   if (led3val < lighthed3) led3val++;
   if (led3val > lighthed3) led3val--;}
////////////////////////////////////////

if( deger < led1val )
   {
   output_low(led1);
   }
else
   {
   output_high(led1);
   }

if( deger < led2val )
   {
   output_low(led2);
   }
else
   {
   output_high(led2);
   }

if( deger < led3val )
   {
   output_low(led3);
   }
else
   {
   output_high(led3);
   }
   
//!   printf(lcd_putc,"\f Y=%u M=%u K=%u", led1val,led2val,led3val);
//!   delay_ms(10);
}

}
/////////////////////////////////////////


Arkadaşlar bu kodu kullanarak birşeyler yapmaya başladım şimdi de. Şöyle bir problem var. led1 led2 led3 pinlerine bağlı renklerden led1 led2 sürekli değişirken led3 pinine bağlı led hiçbir zaman değişmiyor. Oraya RGB nin kırmızı bacağını bağladım. Sürekli HİGH durumda . Sizce problem ne. ?

Önce RA2 deydi o pin, dedim belki referans voltajdan dolayı öyle oluyordur dedim RA3 e aldım değişen birşey yok. Sanırım programda bir problem var.