Haberler:

Foruma Resim Yükleme ve Boyut Sınırlaması ( ! )  https://bit.ly/2GMFb8H

Ana Menü

Software PWM

Başlatan django, 16 Ağustos 2014, 19:17:09

django

Arkadaşlar ben elektroniğe Arduino ile başladım. Arduino'dan sonra Atmel entegrelerinle oynamaya başladım. Oynadığım entegreler Attiny gibi genellikle HPWM destekleyen entegrelerdi.

PIC16F628A ile PIC'e başlamayı düşündüm. Bu entegreye 20Mhz kristal bağlayıp software PWM alınabilir mi?

Bu linkte ADC kullanmadan fotosel okuma yöntemini göstermiş ve ben bunu uygulayarak rastgele veriler alıp RGB led sürmek istiyorum.

Yani kullanmak istediğim fonksiyon duty oranı ayarlanabilmeli, bunun için yardımlarınız bekliyorum.

Ayrıca şu Arduino kütüphanesini de inceledim: http://code.google.com/p/rogue-code/

XX_CİHAN_XX

Timer kesmelerini kullanarak başarılı bir şekilde softPwm yapabilirsin. Pwm mantığını düşün bir duty cycle değerin bir de periyot değerin var. Buna göre timer kesmenin bölenlerini hesaplayıp kuracaksın. Timer sayıcısının duty değeri kadarlık kısmında çıkışın high konumda kalırken geri kalan kısmında da low konuma geçecek. Örneğin bir TMR0 sayıcısını kesmeli bir şekilde istediğin periyotta çalıştırmak için neler yapmak gerektiğini araştırarak işe başlayabilirsin sonrası zaten çorap söküğü gibi gelecektir.
Yirmi yaşındaki bir insan, dünyayı değiştirmek ister . Yetmiş yaşına gelince , yine dünyayı değiştirmek ister, ama yapamayacağını bilir.

t2

#2
PlC SoftPwm var. Mümkün.


mesaj birleştirme:: 16 Ağustos 2014, 21:51:44

http://ramazansubasi.net/xc8-12f675-ile-5-kanal-yazilimsal-pwm/

django

https://www.picproje.org/index.php/topic,38431.15.html burada sanırım cevabımı buldum. Ayrıca http://www.best-microcontroller-projects.com/pic-pwm-interrupt.html şurada iki adet TMR kullanılırsa daha performanslı olacağından bahsedilmiş, datasheette 3 adet timer saydım. İlk linkteki kodu, iki timerlı olana uyarlamalı mı, yoksa tek timerlı olan işimi görür mü?

Ayrıca bir şey daha danışmak istiyorum, verdiğim fotosel örneğini kullanarak PIC'de de pot okuyabilirim, çünkü MCU'mda ADC yok?

Sanırım bahsettiğiniz timer kesmenin bölenleri burada `set_timer1(65185)` ile ayarlanmış. Datasheet'te okuduğuma göre Timer1 32khz, ikinci verdiğim linkte okuduğuma göre PWM Frekansını Timer frekansını adım sayısına bölerek kullanıyoruz. Yani ben 8 bit PWM elde etmek istediğimde 32768/256 = 128Hz'lik PWM mi elde etmiş olurum? Forumdaki arkadaş 56Hz olduğunu söylemiş. Ayrıca buradaki '65185' nedir?

Ayrıca Datasheette diğer timerların frekansları yok. Hepsi mi 32Khz ?

Tagli

Timer frekansı sabit değildir, sen nasıl ayarlarsan öyle olur. Pek çok seçenek mevcut, datasheet'i incele.

Bu arada, PIC16F628A'nın PWM modülü var zaten, yazılımsal PWM yapmana gerek yok.
Gökçe Tağlıoğlu

RaMu

#5
Alıntı yapılan: django - 16 Ağustos 2014, 19:17:09

Bu linkte ADC kullanmadan fotosel okuma yöntemini göstermiş ve ben bunu uygulayarak rastgele veriler alıp RGB led sürmek istiyorum.


Adc kullanmadan
kısmını yanlışlıkla yazmış olabilir misin?
Linkte adc kullanılıyor.
Bonus yazan ikinci kısımda anlatılmış.

Bu arada 16f628a da ADC yoktur,
fotosel okumak istiyorsan başka pic seçmen işini kolaylaştırır.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

LukeSkywalker

#6
http://www.biltek.tubitak.gov.tr/gelisim/elektronik/dosyalar/30/rgb_termometre.pdf

mesaj birleştirme:: 17 Ağustos 2014, 08:48:29

Evet verdiğiniz linkin alt kısmında LDR'nin alt tarafına bağlanan kapasitenin dolma süresine göre ADC kullanmadan dijital olarak ölçüm yapmış. Gayet mantıklı bir uygulama.

İlk önce ölçüm yapılacak pin çıkış olarak ayarlanıyor ve 0'a çekiliyor. Böylece kapasite deşarj ediliyor belli bir süre. Daha sonra Pin giriş olarak ayarlanıyor ve high konuma geçene kadarki süre ölçülüyor. LDR direncine bağlı olarak bu süre değişiyor haliyle. Yani eğer ortam karanlık ise şarj süresi uzuyor, aydınlık ise kısalıyor. Bu süre baz alınarak ledin parlaklığı değiştiriliyor.

Bu yöntemi kullanarak  16F628A ile istediğiniz uygulamayı yapabilirsiniz.

Verdiğim linkte nasıl yazılımsal PWM oluşturulabileceği gösterilmiş. Sizin yapmanız gereken şey iki mantığı birleştirebilmek.

Tagli

Alıntı yapılan: django - 17 Ağustos 2014, 00:31:51
Ayrıca bir şey daha danışmak istiyorum, verdiğim fotosel örneğini kullanarak PIC'de de pot okuyabilirim, çünkü MCU'mda ADC yok?
LukeSkywalker örneğini vermiş. Öğretici bir örnek olsa da bence şu günlerde anlamsız. Mikrodenetleyicilerin hemen hepsinde ADC ve bol miktarda analog giriş bacağı bulunuyor. Öyle ki 16F628A bu konuda istisna sayılabilir. Onunla uğraşmaktansa mesela 16F88 gibi daha yeni bir model tercih edilebilir.
Gökçe Tağlıoğlu

LukeSkywalker

Bu uygulama için 12f675 gibi bir mcu bile yeterli olacaktır.

django

Elimde başka donanım alacak param yok ne yazık ki bunu kullanarak yapmalıyım.

Aklımda bazı şeyler şekillenmeye başladı, fakat şu noktada takıldım.

Burada https://www.picproje.org/index.php/topic,38431.15.html sadogan'ın postunda iki kere set_timer1 kullanılmış. Benim anlamadığım noktada birinde 15000 civarı değer kullanılırken neden ikincide 65000 civarı değer kullanılmış. Timer1 16 bit olduğunu biliyorum, fakat neden böyle bir şey yapılmış?

LukeSkywalker, verdiğiniz PDF'e baktım.RGB_on fonksiyonunda iki kere for neden kullanılıyor? Biraz daha açmam gerekirse neden 25'lik döngü kullanılıyor? 255'lik kullanılsa yeterli olmaz mı?

Ayrıca 10 uS nasıl hesaplanmış?

LukeSkywalker

Son sorunuzdan başlayalım.
10us kullanması için herhangi bir hesap yaptığını sanmıyorum. Sadece frekansı belirlemek amacıyla 10us'lik bir gecikme kullanmış orada. Siz bu değeri değiştirerek gözlem yapabilirsiniz.

Sensörden her okunan değer için 25 kez aynı rengi göstermiş. Renk değişiminin çok hızlı olmasını engellemek açısınıdan böyle bir şey yapmış. Sadece tek for döngüsü de kullanabilirsiniz. İlla 255 olmasına gerek yok hem de orayı 100,1000,5000 gibi değerlerlede değiştirebilirsiniz değişken tiplerine dikkat ederek. Bu programda PWM çözünürlüğü 8 bit olarak ayarlanmış.

django

@LukeSkywalker , sorularımı cevapladığınız için teşekkür ederim. Peki timer interrupt kullanarak CCS'de PWM oluştururken set_timerx fonksiyonlarını görüyorum. Yukarıda da dediğim gibi
#include <16f628a.h>          
#FUSES NOWDT                    
#FUSES HS                       
#FUSES PUT                    
#FUSES NOPROTECT                
#FUSES NOBROWNOUT               
#FUSES NOMCLR                   
#FUSES NOCPD                    
#use delay(clock=20000000)
unsigned int8 pwm_valA=0,pwm_valB=0,pwm_dutyA=0,pwm_dutyB=0;
#int_timer1
void timer1_kesmesi()
{
     
      set_timer1(65185);//20mhz kristai ile 70usn
      if(++pwm_valA<pwm_dutyA)output_high(pin_a1);
      else output_low(pin_a1);
      if(++pwm_valB<pwm_dutyB)output_high(pin_a2);
      else output_low(pin_a2);      
} 
void McuInit()
{
    setup_comparator(NC_NC_NC_NC);
    set_tris_a(0b11111001);
    set_timer1(15035);// soft pwm
    setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);// soft pwm
    
    setup_timer_2(T2_DIV_BY_1,255,1);// hard pwm 19.8khz
    setup_CCP1(CCP_PWM);// hard pwm
    set_pwm1_duty(0);// hard pwm
}
void main()
{
   McuInit();
   enable_interrupts(int_timer1);// soft pwm
   enable_interrupts(GLOBAL);// soft pwm
   while(TRUE)
   {
       pwm_dutyA=75;// soft pwm
       pwm_dutyB=50;// soft pwm
       set_pwm1_duty(100);// hard pwm
   }

}

burada iki kere set_timer kullanılmış. Bu konuyla iki sorum olacak.

1- Neden iki kere fonksiyon kullanılmış?
2- Aldığı argüman neye göre verilir?

İnternetten CCS dökümanı aradım fakat bulamadım.

LukeSkywalker

Burada Timer2 kullanılarak hardware PWM kullanılmış. Ama duty olarak 0 değeri girmiş. Yani hardware pwm şu anda aktif edilmiş fakat çıkış üretmiyor veya daha doğru bir söylemle 0 çıkışı üretiyor sadece.  Orada timer2'nin kullanılması şu hali ile gereksiz.

sadogan

#13
@django
Alıntı Yap
Sanırım bahsettiğiniz timer kesmenin bölenleri burada `set_timer1(65185)` ile ayarlanmış. Datasheet'te okuduğuma göre Timer1 32khz,
ikinci verdiğim linkte okuduğuma göre PWM Frekansını Timer frekansını adım sayısına bölerek kullanıyoruz.
Yani ben 8 bit PWM elde etmek istediğimde 32768/256 = 128Hz'lik PWM mi elde etmiş olurum? Forumdaki arkadaş 56Hz olduğunu söylemiş. Ayrıca buradaki '65185' nedir?

Datasheet eksik okumusun Tmr1 32khz deyil tmr1 source clock girişleri var bunlardan 1 tanesi 32768hz kristal bağlana bilen bir girisi.Tmr1 istenirse buna yada sistem clock una yada harici
bir clock kaynagına bağlana bilir.
Alıntı Yap
ikinci verdiğim linkte okuduğuma göre PWM Frekansını Timer frekansını adım sayısına bölerek kullanıyoruz.
Bu doğru
Alıntı Yap
Yani ben 8 bit PWM elde etmek istediğimde 32768/256 = 128Hz'lik PWM mi elde etmiş olurum?
Ama bu bahsetigin açıklamaya uygun olamdıgı için Olmazsın buldugun bu deger pwm frekansını 256 da biri  .
Alıntı Yap
Ayrıca buradaki '65185' nedir?
Tmr1 16 bitlik bir sayac Tmr1 interruptu açık oldugunda sayac doldugunda interrupt üretir.
kristal frekansı 20 mhz iken Tmr1 clk girisine 5mhz kare dalga gelir(datasheet ten bakmıssınızdır). Bu durumda tmr1 sayıcısı 1sn/5mhz= 0.2 uSn yede bir artar 16 bit sayıcı 65535 en sonra tekrar
0'a döneceğinden 65536*0.2uSn = 13107.2 uSn de interrut üretir buda f=1/T den  1000000uSn/ 13107.2 = 76.2 hz olur yeni tmr1 saniyede 76.2 kez interrut a girer.
Ama bize 8 bit cözünürlügünde ve frekamsı  50 hz dolaylarında bir pwm gerektiğinde 50*256 = 12800 interupta girmesi gerekiyor.
Tmr1 sayacını ön yükleyerek 65185 den başlatırsak tmr1 sayacı önyükleme değerinden saymaya başlar.
Tmr1 doldugnda 65536-65185= 351 artış yapmıştır her artış 0.2 uSn pwm peryodu = 351*0.2*256= 17971.2 uSn pwm frekansı 1000000uSn/17971.2 = 55.54 hz oluyor.

Alıntı Yap
burada iki kere set_timer kullanılmış. Bu konuyla iki sorum olacak.

1- Neden iki kere fonksiyon kullanılmış?
2- Aldığı argüman neye göre verilir?

1- Dikkat edersen McuInit fonksiyonunda kullanılmış işlemci kunlanıma hazırlanmış ve pwm başlangıçk değeri '0'  atanmış
bunun nedeni main fonksiyona girene kadar pwm değerini rasgele bir yerden başlamasını önlemek için.
2- Pwm duty ne olmasını istiyorsan 

Alıntı yapılan: LukeSkywalker - 18 Ağustos 2014, 09:54:25
Burada Timer2 kullanılarak hardware PWM kullanılmış. Ama duty olarak 0 değeri girmiş. Yani hardware pwm şu anda aktif edilmiş fakat çıkış üretmiyor veya daha doğru bir söylemle 0 çıkışı üretiyor sadece.  Orada timer2'nin kullanılması şu hali ile gereksiz.
Sanırım main içine dikkat etmediniz.

LukeSkywalker

#14
@sadogan doğru söylüyor, gözümden kaçmış,  main içerisinde ;
set_pwm1_duty(100);// hard pwm

satırı ile duty saykıl değerini 100 olarak ayarlamış.

@django Burada yazılımsal pwm oluşturma ile timer2 kurulumunun hiç bir bağlantısı yok. timer2 donanımsal pwm'i beslediği için kullanılmış. Bu örnekte sanırım yazılımsal pwm oluşturma ile donanımsal pwm kullanımını birarada göstermek istemiş.

Siz sadece yazılımsal pwm kullanacaksanız  diğer ayarlamaları yapmanıza gerek yok.