Bit Angle Modulation Problemi?

Başlatan Mucit23, 07 Mart 2017, 16:51:12

Mucit23

Bit Angle Modulation ile ilgili bir problemim var. İşlem yükünü azaltmak için farklı yöntemler deniyorum. Bu yöntemde her bir bit için kesmenin periyodunu değiştiriyorum. LED2 isimli led'de 4 bit renk çözünürlüğü elde etmeye çalışıyorum.

Modülasyon için bir tane timer kullandım. Dediğim gibi Timer'in sürekli periyodunu değiştirerek bit genişliklerini ayarlıyorum. Şöyle bir algoritma kurdum. 4 bit renk çözünürlüğü için uğraşıyorum.

CY_ISR(InterruptHandler)   //Kesme fonksiyonu
{
   Timer_1_STATUS;  //Kesme bayrakları temizleniyor. 
    
   LED1_Write(1-LED1_Read());  //Kesme oluşum sürelerini ölçmek için kullandım

   LED2_Write(((Duty_Val>>bitmask)& 0x01));   //Parlaklığını ayarlayacağım led, 1 yazarsam led yanar, 0 yazarsam led söner
   Timer_1_WritePeriod(((uint16_t)1<<bitmask)*100); //Periyot değeri için ((uint16_t)1<<bitmask)*100 işlemini yaptım. 
   bitmask++;if(bitmask>3)bitmask=0;  //Bit mask 0 iken periyot değeri 100uS olurken bit mask değeri 3 iken 800uS olur. 
}

minimun bit genişliği 100uS olacak şekilde ayarlamam gerekiyor. Bu yüzden Timerin giriş frekansını 1Mhz yaptım. Timer period değerini 100 yaparsam tam 100uS'de kesme oluşuyor. 4 bit için en büyük bit genişliği 800uS olur. buraya kadar sıkıntı yok.

Yukarıdaki kod çalışıyor nispeten ama bitler kaymış olarak çıkıyor

Örneğin Duty_Val=0b00000101 olursa çıkışta 0b00001010 verisini görüyorum.

Aynı işlemi kesme içerisinde değilde ana program döngüsünde yaparsam problem yok.
Ana programda aşağıdaki kodlar tam istediğim gibi çalışıyor. Timer Kullanmak yerine delay fonksiyonu kullandım.
   
   LED1_Write(1-LED1_Read());  //Kesme oluşum sürelerini ölçmek için kullandım

   LED2_Write(((Duty_Val>>bitmask)& 0x01));   //Parlaklığını ayarlayacağım led, 1 yazarsam led yanar, 0 yazarsam led söner
   CyDelayUs(((uint16_t)1<<bitmask)*100); //Periyot değeri için ((uint16_t)1<<bitmask)*100 işlemini yaptım. 
   bitmask++;if(bitmask>3)bitmask=0;  //Bit mask 0 iken periyot değeri 100uS olurken bit mask değeri 3 iken 800uS olur.


Kafam durdu resmen. 4 Bit renk çözünürlüğü elde ettiğimi düşünüyordum ama bu problem var. Kesme kullanınca neden bu tür bir kayma olabilir?

agora_meyhanesi42

Bilgiyi göndermeden önce 9.cu bir biti ilk olarak yollayıp kesmeye girmesini sağlarsanız  yani 8 bitlik veriden önce bir bit yollayip kesmeye girerseniz daha sonrada bu bitin yaklasik suresi kadar kesme icinde bekleyip gelen bilgiyi okuyarak yaparsanız bence sorun düzelir
Yüksel Türk ! Senin için yükselmenin hududu yoktur...

Mucit23

Sistemin kendi içerisinde otonom çalışması gerekiyor. Yani herşey bitmask değişkeninin değerine göre şekilleniyor olması lazım
Yaptığım işlemleri yazıya dökeyim belki göze çarpan birşey çıkar


  • Timer'i ilk başta çalıştırmadan önce preload değerini 100 yapıyorum ki 100uS sonra kesme oluşsun.
    Bu arada bitmask değeri 0 dır. 
  • 100uS sonra kesme oluşunca Duty değerinin 0. bitini LED'e gönderiyorum. (bitmask=0) İlgili kodlar LED2_Write(((red_bits[0]>>bitmask)& 0x01));
  • Bitmask değeri hala 0 iken Timer preload değerini ayarlıyorum.    Timer_1_WritePeriod(((uint16_t)1<<bitmask)*100); bitmask değeri 0 için preload değeri 100 olurken bitmask değeri 3 iken preload değeri 800 olması lazım. Lojik analyser'da gecikme değerlerini doğruluyorum.
  • bitmask değerini kesmeden çıkmadan önce 1 arttırıyorum. Eğer bitmask değeri 3'den büyük olursa bitmask değerini sıfırlıyorum.    bitmask++;if(bitmask>3)bitmask=0;

Sorun gören var mı?

Mucit23

Sorunu çözdüm. Perload değeri yazılırken bir sonraki bit için yazılması gerekiyordu.

Şimdi gayet iyi çalışıyor fakat şöyle bir sorun tespit ettim.

Işık değişimi lineer bir şekilde değişmiyor.  Yani çıkıştaki veri 0b00000100 iken 0b00000101 olduğunda ışık şiddeti gözle farkedilmeyecek kadar az değişiyor. aynı şekilde 0b00000110 olduğunda da çok az bir değişim gözlemleniyor.

Fakat ledin yanık kalma sürelerine baktığımda artımın lineer olduğunu görüyorum.

4 bit için toplam periyot 1500us idi
0b0001 verdiğimde ledin yanık kalma süresi 100uS
0b0010 verdiğimde ledin yanık kalma süresi 200uS
0b0011 verdiğimde ledin yanık kalma süresi 100+200=300uS
0b0100 verdiğimde ledin yanık kalma süresi 400us
.
.
0b1110 verdiğimde ledin yanık kalma süresi 800+400+200=1400uS
0b1111 verdiğimde ledin yanık kalma süresi 1500uS
Normalde yanık kalma sürelerine baktığımda lineer bir değişim olduğu görülüyor ama gerçekte böyle olmuyor. Bunu çözmem lazım.

kantirici

LED'ler lineer eleman olmadıkları için cevaplarıda lineer olmuyor. Lineer dim için çeşitli yöntemler var. Onları dikkate alarak süreleri hesaplamak gerek.

Mucit23

Şuan RGB P10 Panellerle uğraşıyorum. Tek satır aktif iken baya iyi bir sonuç aldım.  Ama işin içine birde yatay tarama girince bazı problemler oluşuyor. Bahsettiğim problemler o zaman oluyor. Onu çözersem tamamdır.

Zoroaster

Seytan deliginden kacti.

Mucit23

Hocam genel olarak çözdüm sorunu.

Lineerlikten kastım ışık şiddetinin göze çarpmayacak bir şekilde değişmesiydi. Taramadan kaynaklı bir sorun vardı ki bunu büyük bir oranda hallettim sayılır. 32x16=512 RGB LED'e PWM uygulayabildim. Şuanda her renk 4 bit ama işlemlerimi optimize edebilirsem eğer renk başına 6 bit renk çözünürlüğünü yakalayabilirim.