- PWM Sinyali nedir?
- GPIO Pinlerinde PWM oluşturmak için PIC'i programlama
- Devre şeması
- Simülasyon
- PIC Mikrodenetleyiciyi kullanarak Servo Motoru kontrol etmek için Donanım Kurulumu
PWM sinyal üretimi, her gömülü mühendis cephaneliğinde hayati bir araçtır, servo motorun konumunu kontrol etmek, dönüştürücüler / invertörlerdeki birkaç güç elektroniği IC'sini değiştirmek ve hatta basit bir LED parlaklık kontrolü gibi birçok uygulama için çok kullanışlıdır. PIC mikro denetleyicilerinde PWM sinyalleri, gerekli Kayıtları ayarlayarak Karşılaştırma, Yakalama ve PWM (CCP) modülleri kullanılarak üretilebilir, bunu PIC PWM öğreticisinde nasıl yapacağımızı zaten öğrendik. Ancak bu yöntemin önemli bir dezavantajı var.
16F877A ÇKP modülleri kullanırsanız, sadece pimleri RC1 ve RC2 üzerinde PWM sinyallerini üretebilir. Ancak, PWM işlevselliğine sahip olmak için daha fazla pime ihtiyacımız olan durumlarla karşılaşabiliriz. Örneğin benim durumumda, CCP modülünün umutsuz olduğu robotik kol projem için 6 RC servo motoru kontrol etmek istiyorum. Bu senaryolarda , GPIO pinlerini zamanlayıcı modülleri kullanarak PWM sinyalleri üretecek şekilde programlayabiliriz. Bu şekilde, gerekli herhangi bir pin ile mümkün olduğunca çok PWM sinyali üretebiliriz. Çoklayıcı IC kullanmak gibi başka donanım korsanları da var, ancak programlama yoluyla aynı şey elde edilebildiğinde neden donanıma yatırım yapalım? Bu eğitimde, bir PIC GPIO pinini PWM pinine nasıl dönüştürebileceğimizi öğreneceğiz ve test etmek için dijital osiloskop ile proteus üzerinde simüle edeceğiz ve ayrıcaPWM sinyalini kullanarak Servo motorun konumunu kontrol edin ve bir potansiyometreyi değiştirerek görev döngüsünü değiştirin.
PWM Sinyali nedir?
Ayrıntılara girmeden önce, PWM Sinyallerinin ne olduğunu biraz tazeleyelim. Darbe Genişlik Modülasyonu (PWM), en yaygın olarak kontrol devrelerinde kullanılan dijital bir sinyaldir. Bu sinyal, önceden tanımlanmış bir süre ve hızda yüksek (5v) ve düşük (0v) olarak ayarlanır. Sinyalin yüksek kaldığı süreye "açık kalma süresi" ve sinyalin düşük kaldığı süre "kapalı kalma süresi" olarak adlandırılır . Aşağıda tartışıldığı gibi bir PWM için iki önemli parametre vardır:
PWM'nin görev döngüsü
PWM sinyalinin YÜKSEK (açık kalma süresi) kaldığı sürenin yüzdesi görev döngüsü olarak adlandırılır. Sinyal her zaman AÇIK ise% 100 görev döngüsündedir ve her zaman kapalıysa% 0 görev çevrimidir.
Görev Döngüsü = Açma süresi / (Açma süresi + Kapatma süresi)
Değişken ismi |
İfade eder |
PWM_Frequency |
PWM Sinyalinin Frekansı |
T_TOTAL |
Bir tam PWM döngüsü için harcanan toplam süre |
TON |
PWM sinyali zamanında |
T_OFF |
PWM sinyalinin kapanma süresi |
Görev döngüsü |
PWM sinyalinin görev döngüsü |
Şimdi, matematik yapalım.
Bu, frekansın basitçe zamanın tersi olduğu standart formüllerdir. Frekans değeri, kullanıcı tarafından uygulama gereksinimine göre belirlenmeli ve ayarlanmalıdır.
T_TOTAL = (1 / PWM_Frequency)
Kullanıcı Görev döngüsü değerini değiştirdiğinde, programımız T_ON süresini ve T_OFF süresini buna göre otomatik olarak ayarlamalıdır. Dolayısıyla, yukarıdaki formüller, Duty_Cycle ve T_TOTAL değerine dayalı olarak T_ON'u hesaplamak için kullanılabilir.
T_ON = (Duty_Cycle * T_TOTAL) / 100
Bir tam döngü için PWM sinyalinin Toplam süresi, açma ve kapama sürelerinin toplamı olacağından. Biz yapabilirsiniz kapalı süresini T_off hesaplamak yukarıda gösterildiği gibi.
T_OFF = T_TOTAL - T_ON
Bu formülleri aklımızda tutarak PIC mikro denetleyicisini programlamaya başlayabiliriz. Program, POT'tan ADC değerine göre değişen bir Görev döngüsüne dayalı bir PWM sinyali oluşturmak için PIC Zamanlayıcı Modülü ve PIC ADC Modülünü içerir. Bu modülleri kullanmakta yeniyseniz, köprülere tıklayarak uygun öğreticiyi okumanız şiddetle tavsiye edilir.
GPIO Pinlerinde PWM oluşturmak için PIC'i programlama
Bu eğiticinin tam programı, her zaman olduğu gibi web sitesinin alt kısmında bulunabilir. Bu bölümde programın gerçekte nasıl yazıldığını anlayalım. Tüm programlar gibi, konfigürasyon bitlerini ayarlayarak başlıyoruz. Benim için ayarlamak için hafıza görünümleri seçeneğini kullandım.
// CONFIG #pragma config FOSC = HS // Osilatör Seçim bitleri (HS osilatörü) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT devre dışı) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT devre dışı) #pragma config BOREN = ON // Brown-out Reset Etkinleştirme biti (BOR etkin) #pragma config LVP = OFF // Düşük Voltaj (Tek Besleme) Devre İçi Seri Programlama Etkinleştirme biti (RB3 dijital I / O'dur, MCLR üzerindeki HV, programlama için kullanılmalıdır) #pragma config CPD = OFF // Veri EEPROM Hafıza Kodu Koruma biti (Veri EEPROM kod koruması kapalı) #pragma config WRT = OFF // Flash Program Hafıza Yazmayı Etkinleştir bitleri (Yazma koruması kapalı; tüm program hafızasına EECON kontrolü tarafından yazılabilir) #pragma config CP = KAPALI // Flash Programı Bellek Kodu Koruma biti (Kod koruması kapalı) // #pragma yapılandırma deyimleri proje dosyası içermeden önce gelmelidir. // AÇIK ve KAPALI için #define yerine proje numaralandırmalarını kullanın. #Dahil etmek
Daha sonra donanımda kullanılan saat frekansından bahsediyoruz, burada benim donanımım 20MHz kristal kullanıyor, donanımınıza göre değeri girebilirsiniz. Bunu PWM sinyalinin frekans değeri takip eder. Buradaki amacım, 50Hz'lik bir PWM frekansı gerektiren bir hobi RC servo motorunu kontrol etmek olduğundan, Frekans değeri olarak 0.05KHz ayarladım, bunu uygulama gereksinimlerinize göre de değiştirebilirsiniz.
#define _XTAL_FREQ 20000000 #define PWM_Frequency 0.05 // KHz (50Hz) cinsinden
Şimdi, Frekans değerine sahip olduğumuza göre , T_TOTAL'ı yukarıda tartışılan formülleri kullanarak hesaplayabiliriz. Milisaniye cinsinden zamanın değerini almak için sonuç 10'a düşürülür. Benim durumumda T_TOTAL değeri 2 mili saniye olacaktır.
int T_TOTAL = (1 / PWM_Frequency) / 10; // frekanstan Toplam Zamanı hesapla (milisaniye cinsinden) // 2 msn
Bunu takiben, ADC PIC eğitimimizde tartışıldığı gibi Potansiyometrenin konumunu okumak için ADC modüllerini başlatıyoruz. Daha sonra, her seferinde çağrılacak olan Interrupt servis rutinine sahibiz, timer overflows buna daha sonra geri döneceğiz, şimdilik ana fonksiyonu kontrol edelim.
Ana işlevin içinde zamanlayıcı modülünü yapılandırıyoruz. Burada Timer modülünü her 0.1 ms'de bir taşacak şekilde yapılandırdım. Zamanın değeri aşağıdaki formüller kullanılarak hesaplanabilir
RegValue = 256 - ((Delay * Fosc) / (Prescalar * 4)) saniye cinsinden gecikme ve hz cinsinden Fosc
Benim durumumda, 64 ön skalar ve 20 MHz Fosc ile 0.0001 saniyelik (0.1 ms) bir gecikme için kaydımın (TMR0) değeri 248 olmalıdır. Yani konfigürasyon şöyle görünür
/ ***** Zamanlayıcı için Bağlantı Noktası Yapılandırması ****** / OPTION_REG = 0b00000101; // Harici frekansı olan Timer0 ve prescalar olarak 64'ü // Ayrıca PULL UP'ları Etkinleştirir TMR0 = 248; // 0.0001s için zaman değerini yükle; delayValue yalnızca 0-256 arasında olabilir TMR0IE = 1; // PIE1 kaydında zamanlayıcı kesinti bitini etkinleştir GIE = 1; // Global Kesmeyi Etkinleştir PEIE = 1; // Çevre Birimi Kesmesini Etkinleştir / *********** ______ *********** /
Ardından Giriş ve Çıkış konfigürasyonunu ayarlamamız gerekir. Burada ADC değerini okumak için AN0 pinini ve PWM sinyallerini çıkarmak için PORTD pinlerini kullanıyoruz. Bu yüzden onları çıkış pinleri olarak başlatın ve aşağıdaki kod satırlarını kullanarak onları düşük yapın.
/ ***** G / Ç ****** / TRISD = 0x00 için Bağlantı Noktası Yapılandırması ; // MCU'ya PORT D üzerindeki tüm pinlerin çıkış PORTD = 0x00 olduğunu bildir; // Tüm pinleri 0 / *********** ______ *********** olarak başlat /
Sonsuz while döngüsünün içinde, görev döngüsünden on time (T_ON) değerini hesaplamalıyız. Açık kalma süresi ve görev döngüsü, POT'un konumuna bağlı olarak değişir, bu nedenle bunu aşağıda gösterildiği gibi while döngüsü içinde tekrar tekrar yaparız. 0.0976, 100 almak için 1024 ile çarpılması gereken değerdir ve T_ON'u hesaplamak için mili saniye cinsinden değer elde etmek için 10 ile çarptık.
while (1) { POT_val = (ADC_Read (0)); // ADC Duty_cycle = (POT_val * 0.0976) kullanarak POT değerini okuyun ; // 0 ila 1024 ila 0 ila 100 eşleştir T_ON = ((Duty_cycle * T_TOTAL) * 10/100); // Formül birimini mil saniye cinsinden kullanarak Açma Zamanı'nı hesaplayın __delay_ms (100); }
Zamanlayıcı her 0.1 ms için aşırı akışa ayarlandığından, zamanlayıcı kesinti servis rutini ISR her 0.1 ms için çağrılacaktır. Servis rutininin içinde count adlı bir değişken kullanıyoruz ve her 0.1 ms için artırıyoruz. Bu şekilde zamanı takip edebiliriz. PIC mikro denetleyicideki Kesmeler hakkında daha fazla bilgi edinmek için bağlantıları takip edin.
if (TMR0IF == 1) // Zamanlayıcı aşımı nedeniyle zamanlayıcı bayrağı tetiklendi -> her 0,1 ms için taşmaya ayarlı { TMR0 = 248; // Zamanlayıcı Değerini Yükle TMR0IF = 0; // timer interrupt flag sayımını temizle ++; // Her 0,1 ms için artışları say -> count / 10, ms cinsinden count değerini verir }
Son olarak, GPIO pinini T_ON ve T_OFF değerlerine göre değiştirme zamanı. Biz var sayımı mili saniye cinsinden zaman izler değişkeni. Biz zaman daha az olup olmadığını kontrol etmek o değişkeni kullanan Yani zamanında evet o zaman biz bunu kapatmak başka açık GPIO pin tutarsak, ve tutmak yeni çevrimi başlayana kadar kapalı. Bu, bir PWM döngüsünün toplam süresiyle karşılaştırılarak yapılabilir. Aynısını yapmak için kod aşağıda gösterilmiştir
if (count <= (T_ON)) // Eğer süre, süreden az ise RD1 = 1; // GPIO'yu aç yoksa RD1 = 0; // Aksi takdirde GPIO'yu kapat if (count> = (T_TOTAL * 10)) // Yeni bir döngü başlayana kadar kapalı tutun count = 0;
Devre şeması
PIC mikrodenetleyicisinin GPIO pini ile PWM oluşturmak için devre şeması gerçekten basittir, sadece PIC'e osilatör ile güç verin ve potansiyometreyi AN0 pinine ve Servo Motoru RD1 pinine bağlayın, PWM sinyalini almak için GPIO pinini kullanabiliriz, seçtim RD1 sadece rastgele. Hem Potansiyometre hem de Servo motor, aşağıda devre şemasında gösterildiği gibi 7805'ten düzenlenen 5V ile çalıştırılır.
Simülasyon
Projeyi simüle etmek için proteus yazılımımı kullandım. Aşağıda gösterilen devreyi oluşturun ve kodu simülasyonunuza bağlayın ve çalıştırın. Programımıza göre RD1 GPIO pininde bir PWM sinyali almalısınız ve PWM'nin görev döngüsü potansiyometrenin konumuna göre kontrol edilmelidir. Aşağıdaki GIF, potansiyometre ile ADC değeri değiştirildiğinde PWM sinyalinin ve servo motorun nasıl tepki verdiğini göstermektedir.
PIC Mikrodenetleyiciyi kullanarak Servo Motoru kontrol etmek için Donanım Kurulumu
Tüm donanım kurulumum aşağıda gösterilmiştir, eğitimlerimi takip eden kişiler için bu pano tanıdık gelmelidir, şimdiye kadar tüm eğitimlerimde kullandığım pano. Nasıl inşa ettiğimi öğrenmekle ilgileniyorsanız, Yanıp Sönen LED eğitimine başvurabilirsiniz. Aksi takdirde yukarıdaki devre şemasını takip edin ve her şey yolunda gitmelidir.
Programı yükleyin ve potansiyometreyi değiştirin; servonun potansiyometrenin konumuna göre konumu değiştirdiğini görmelisiniz. Projenin tam çalışması bu sayfanın sonunda verilen videoda gösterilmektedir. Umarım projeyi anladınız ve inşa etmekten keyif aldınız, eğer sorularınız varsa, forumda yayınlamaktan çekinmeyin ve cevaplamak için elimden geleni yapacağım.
Bu projeyi, halihazırda inşa ettiğimiz Arduino Robotik Kol'a benzer şekilde, birden fazla servo motoru kontrol etme seçenekleri ekleyerek ve böylece ondan bir robot kol oluşturarak ilerletmeyi planlıyorum. O zamana kadar görüşürüz !!