Jalv2 – 74HC595 Shift PWM ile Karaşimşek Efekti

İnternette gezerken Jalv2 ile yeni tanıştığım dönemde yapmış olduğum 32 Ledli karaşimşek devresine denk geldim. Kodları ve devreye bakınca ne kadar amatörce yaptığımı fark ettim. İçimde birden güncelleme isteği uyandı. Yapıp kullanacağımdan değil ama belki birilerinin işine yarar diye umut ediyorum.
Daha önce yaptığım devrede orjinal efekt değilde düz yanan ve sağ sola gezen bir efekt vardı. Netten orjinal efekti nasıl yaparım diye araştırırken karşıma Shift PWM konusu çıktı. Özellikle “picproje.org” üyelerinden Ferhat YOL arkadaşımızın yazdığı yazıya denk geldim.
Bknz : http://arectron.com/yazilim/stm32f103-74hc595-ile-shift-pwm.html
Kendisi STM32F103 kullanarak 74HC595 ile Shift PWM uygulamasının nasıl yapılacağını yazmış. Kendisine buradan teşekkürler.
Kullandığı ARM mcu 32 bit olduğu için gayet hızlı. Ama ben PIC ailesinden ufak birşey kullanmayı düşündüğüm için algoritmada farklar yapmam gerekti. Malzeme kutumda 12F683 olduğu için denemelerimi onunla yapmaya karar verdim.
Öncelikle Shift PWM nasıl çalışır ona değinelim.
Bildiğiniz gibi 74HC595 seri giriş paralel çıkış bir kaydırmalı kaydedici entegredir. Özellikle led animasyon devrelerinde, kayan yazılarda çok sık kullanılır. En önemli özelliği veri yüklendikten sonra onu çıkışlara aktarmak olan Latch pinin olmasıdır. Farklı bir modeli olan 74ls164 te bu özellik olmadığı için bazı uygulamalarda özellikle 74HC595 tercih sebebidir.
Eğer 74HC595 ile ShiftPWM yapmak istiyorsak her pinin Lojik 1 veya lojik 0 olma durumunu kontrol etmemiz gerekiyor. Buda yüksek hız isteyen bir algoritmadır.
Mantık olarak istenilen duty değerine göre ilgili pini 1 ya da 0 olarak güncelleyeceğiz. Bu sayede göz yanılması olarak kısık yanan bir led elde ederiz.
Öncelikle Devremizi aşağıdaki gibi kuralım.
Dikkat etti iseniz Kristal değerini 20Mhz olarak seçtim. öncesinde 4-8-16 Mhz denemelerimde istediğim sonucu elde edemedim. Kullandığım PIC 8 bit ve yazdığım algoritma yüzünden olsa gerek en uygun Kristal değeri 20 Mhz olarak gözüküyordu.
Yazılım tarafında TMR0 kesmesini ayarlamak için “http://eng-serve.com/pic/pic_timer.html” sitesinden yardım aldım. Gerekli değerleri girince size ilgili registerlerin nasıl olacağını ve TMR0 için başlangıç değerini gösteriyor.
Ferhat uygulamasında TMR0 için 100 hz , 39 us olacak şekilde kesme yeterli demiş. Ama benim uygulamamda 238Khz ve 4 us uygundu. Belki ben yanlış algoritma kurmuş olabilirim. Ya da kullandığım PIC ‘ in kabiliyeti bu kadar olabilir.
Kesme ve Tarama yordamları
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
-------------- 74HC595 için pin tanımlamaları ------------------ var volatile bit Clock is pin_a2 var volatile bit Enable is pin_a0 var volatile bit Data is pin_a1 ---------------------------------------------------------------- -- Duty değerine göre shift registere Data Gönderir. ---------------------------------------------------------------- Procedure Tarama is var byte dongu for LED_Adet using dongu loop -- Duty Değerini Dizideki değerle karşılaştır. if (duty >= (LED[(LED_Adet-1)-dongu])) then Data = false -- Data 0 else Data = true -- Data 1 end if Clock = high Clock = low -- 74hC595'e gönder end loop Enable = high Enable = low -- Led çıkışa Aktarılsın. duty = (duty + 1) % 255 -- Duty Değerini 1 Arttır. end procedure ---------------------------------------------------------------- -- TMR0 Kesmesi Alt programı ---------------------------------------------------------------- -- Prescaler=1 Preset=235 Freq=238095.24Hz Period=0.000004 seconds const Baslangic = 235 OPTION_REG_T0CS = 0 OPTION_REG_T0SE = 0 OPTION_REG_PSA = 1 OPTION_REG_PS2 = 0 OPTION_REG_PS1 = 0 OPTION_REG_PS0 = 0 INTCON_GIE = 1 -- tüm kesmelere izin verdik. INTCON_TMR0IF = 0 -- Kesme bayrağını sıfırladık TMR0 = Baslangic INTCON_TMR0IE = 1 -- Timer0 kesmesini aktif edildi procedure Tara is pragma interrupt -- Kesme Alt Programları var byte deger = 0 if (INTCON_TMR0IF) then -- TMR0 Kesmesi İse Tarama TMR0 = Baslangic INTCON_TMR0IF = false end if end procedure ---------------------------------------------------------------- |
Yukarıdaki Kod öbeğinde Tara isimli bir prosedür yer almaktadır. Aynı zamanda kesme oluştuğunda işlemci bu prosedürü çalıştırmaktadır. Tara prosedürü çalıştığında Tarama isimli alt prosedüre dallanmaktadır.
Tarama prosedüründe ise verilen duty değer dizisi sürekli karşılaştırılmakta ve ilgili bit 1 yada sıfır yapılarak 74HC595‘e aktarılmaktadır.
Her prosedür çağrıldığında Duty değerinin max 254 olacak şekilde sürekli değeri artmaktadır. Artan Duty değeri ile dizi de verilen değerin karşılaştırılması sağlanarak istenilen Ledin parlaklığı değiştirilmektedir. Çok geniş bir yelpazemiz yok ama LED uygulamalarında işimizi görecektir.
Yazılımın Tamamı aşağıdaki gibi.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
-- ------------------------------------------------------------------------- -- Baslık : 74HC595 Shift PWM Uygulaması ve Kuyruklu Karaşimşek Devresi -- -- Yazar : www.sercanca.com - Sercan TEK -- Compiler : jal jalv24q6 (compiled Oct 25 2016) -- Tarih : 08.06.2018 -- ------------------------------------------------------------------------- include 12f683 pragma target clock 20_000_000 pragma target OSC HS pragma target WDT DISABLED pragma target BROWNOUT DISABLED pragma target FCMEN DISABLED pragma target IESO DISABLED pragma target MCLR INTERNAL OSCCON_SCS = 0 enable_digital_io() -- Tüm girişler ve çıkışlar Dijital pin_a0_direction = output -- Enable pin_a1_direction = output -- Data pin_a2_direction = output -- Clock const LED_Adet = 8 var byte LED[LED_Adet] = {0,0,0,0,0,0,0,0} var byte duty = 1 ---------------------------------------------------------------- -- Gecikme Alt Programı ---------------------------------------------------------------- procedure gecikme(word in us) is for us loop _usec_delay(7) end loop end procedure -------------- 74HC595 için pin tanımlamaları ------------------ var volatile bit Clock is pin_a2 var volatile bit Enable is pin_a0 var volatile bit Data is pin_a1 ---------------------------------------------------------------- -- Duty değerine göre shift registere Data Gönderir. ---------------------------------------------------------------- Procedure Tarama is var byte dongu for LED_Adet using dongu loop -- Duty Değerini Dizideki değerle karşılaştır. if (duty >= (LED[(LED_Adet-1)-dongu])) then Data = false -- Data 0 else Data = true -- Data 1 end if Clock = high Clock = low -- 74hC595'e gönder end loop Enable = high Enable = low -- Led çıkışa Aktarılsın. duty = (duty + 1) % 255 -- Duty Değerini 1 Arttır. end procedure ---------------------------------------------------------------- -- TMR0 Kesmesi Alt programı ---------------------------------------------------------------- -- Prescaler=1 Preset=235 Freq=238095.24Hz Period=0.000004 seconds const Baslangic = 235 OPTION_REG_T0CS = 0 OPTION_REG_T0SE = 0 OPTION_REG_PSA = 1 OPTION_REG_PS2 = 0 OPTION_REG_PS1 = 0 OPTION_REG_PS0 = 0 INTCON_GIE = 1 -- tüm kesmelere izin verdik. INTCON_TMR0IF = 0 -- Kesme bayrağını sıfırladık TMR0 = Baslangic INTCON_TMR0IE = 1 -- Timer0 kesmesini aktif edildi procedure Tara is pragma interrupt -- Kesme Alt Programları var byte deger = 0 if (INTCON_TMR0IF) then -- TMR0 Kesmesi İse Tarama TMR0 = Baslangic INTCON_TMR0IF = false end if end procedure ---------------------------------------------------------------- procedure Efekt(byte in sure) is -- Soldan Sağa Yürü LED[0]=254 gecikme(sure) LED[0]=64 LED[1]=254 gecikme(sure) LED[0]=16 LED[1]=64 LED[2]=254 gecikme(sure) LED[0]=2 LED[1]=16 LED[2]=64 LED[3]=254 gecikme(sure) LED[0]=0 LED[1]=2 LED[2]=16 LED[3]=64 LED[4]=254 gecikme(sure) LED[1]=0 LED[2]=2 LED[3]=16 LED[4]=64 LED[5]=254 gecikme(sure) LED[2]=0 LED[3]=2 LED[4]=16 LED[5]=64 LED[6]=254 gecikme(sure) LED[3]=0 LED[4]=2 LED[5]=16 LED[6]=64 LED[7]=254 gecikme(sure) LED[4]=0 LED[5]=2 LED[6]=16 LED[7]=254 gecikme(sure) LED[5]=0 LED[6]=2 LED[7]=254 gecikme(sure) LED[6]=0 LED[7]=254 gecikme(sure) gecikme(sure) -- Sağdan Sola yürü LED[6]=254 LED[7]=64 gecikme(sure) LED[5]=254 LED[6]=64 LED[7]=16 gecikme(sure) LED[4]=254 LED[5]=64 LED[6]=16 LED[7]=2 gecikme(sure) LED[3]=254 LED[4]=64 LED[5]=16 LED[6]=2 LED[7]=0 gecikme(sure) LED[2]=254 LED[3]=64 LED[4]=16 LED[5]=2 LED[6]=0 gecikme(sure) LED[1]=254 LED[2]=64 LED[3]=16 LED[4]=2 LED[5]=0 gecikme(sure) LED[0]=254 LED[1]=64 LED[2]=16 LED[3]=2 LED[4]=0 gecikme(sure) LED[0]=254 LED[1]=16 LED[2]=2 LED[3]=0 gecikme(sure) LED[0]=254 LED[1]=2 LED[2]=0 gecikme(sure) LED[0]=254 LED[1]=0 gecikme(sure) end procedure forever loop Efekt(65) end loop |
8 çıkışımız olsa da Ben ledleri çifter çifter bağladığım için 16 ledli elde ettim. Üçerli bağlarsanız bence daha güzel olacaktır diye düşünüyorum.
Devrenin Çalışma Videosu :
Kaynak Dosyalar : 12F683-20
Pass : sercanca.com
Bu Uygulamada Neler Öğrenebiliriz ?
- Jalv2 dilinin ile temel kullanımı
- Jalv2 dilinde TMR0 kesmesinin kullanımı
- Jalv2 dilinde Shift register kullanımı
- Jalv2 dilinde Shift PWM kullanımı
- Jalv2 dilinde 12F683 kullanımı ve sigorta ayarları
Başka bir yazıda görüşmek üzere
Sercan TEK
Bende gölgeli arıyordum isabet olmuş. yalnız jalv2 den anlamıyorum başka dilde örnek yok mu ?
Ben Jalv2 kullanıyorum. Eğer başka dilde yazmak isterseniz bu yazıyı referans olarak kullanın.