top of page

PWM #4: SG90 Micro Servo ile PWM Uygulaması

Merhabalar, serimizin dördüncü bölümünde teoriden pratiğe geçiş yapıyoruz! Bu yazıda, PWM tekniğini daha somut bir seviyeye taşıyor ve SG90 Micro Servo motoru kullanarak nasıl uygulama yapabileceğimizi anlatıyoruz.


Önceki yazılarımızda PWM'nin temellerini, onun frekansını ve çözünürlüğünü nasıl ayarlayacağımızı gördük. Şimdiyse, bu bilgileri kullanarak gerçek bir uygulamada SG90 Micro Servo motorunu nasıl kontrol edeceğimizi keşfedeceğiz.


Bu süreçte, Nuvoton'un M031/M032 serisi mikrodenetleyicileri kullanarak bir PWM sinyali oluşturacağız ve bu sinyali değiştirerek servo motoru hareket ettireceğiz.

Hadi, beraber bu uygulamayı inceleyelim!


Robotik ve hobi projelerinde sıkça kullanılan SG90 gibi servo motorların kontrolünde, en yaygın teknik olan Pulse Width Modulation (PWM) tercih edilir. PWM ile doğru frekans ve darbe genişlik ayarları, motorun hassas hareketler gerçekleştirmesini sağlar.


SG90 servo motoru kontrol ederken genellikle 50 Hz frekansında bir PWM sinyali kullanırız. Bu, her 20 milisaniyede bir PWM darbesinin gönderildiği anlamına gelir. Motorun istenen konumuna hareket etmesi için, PWM darbesinin genişliği yani duty cycle'ı ayarlanır.


SG90 için genellikle 0.5 ms'lik bir darbe genişliği (duty cycle) motorun -90° konumuna geleceğini, 1.5 ms'lik bir darbe genişliği motorun 0° konumuna geleceğini ve 2.5 ms'lik bir darbe genişliği motorun 90° konumuna geleceğini belirler. Ancak, bu değerlerin servo motorundan motora değişebileceğini ve belirli bir servo için dokümantasyonun kontrol edilmesi gerektiğini unutmayın.


Sonuç olarak, SG90 gibi bir servo motoru kontrol etmek için, hem PWM sinyalinin frekansını (50 Hz) hem de darbe genişliğini (0.5 ms ila 2.5 ms arası) ayarlamamız gerekmektedir. Bu iki parametre, servo motorun hangi hızda döneceğini ve hangi pozisyona geleceğini belirler. Ancak, motorun hangi açıya geleceğini belirleyen parametre darbe genişliğidir (duty cycle). Frekans genellikle sabittir ve motorun düzgün çalışmasını sağlar, ancak motorun pozisyonunu doğrudan kontrol etmez.


Şimdi bu bilgilerle uygulamamıza geçebiliriz.


PWM sinyalimizi oluştururken belirli değerler üzerinden ilerlememiz gerekiyor. İlk olarak, oluşturacağımız PWM sinyalinin periyodunu 20 ms olarak belirliyoruz. Bu, servo motorumuzun beklediği frekansla uyumlu olmasını sağlar.


PWM sinyalimizin duty cycle'ını ise, SG90 servo motorunun beklediği değerler olan 0.5 ms ve 2.5 ms arasında ayarlayacağız. Bu duty cycle değerleri, servo motorun farklı pozisyonlara hareket etmesini sağlar. Örneğin, 0.5 ms'lik bir duty cycle, servo motorun -90°’de konumlanacağını, 2.5 ms'lik bir duty cycle ise motorun 90°’de konumlanacağını belirtir.


Bu ayarları yapabilmemiz için, mikrodenetleyicimizin çeşitli konfigürasyonlarını da yapmamız gerekiyor. Clock ve pin konfigürasyonları da bu ayarlar arasında yer alıyor. Clock konfigürasyonu, mikrodenetleyicinin ne hızda çalışacağını belirler. Bu ayarlamaları yapmak için Nuvoton'un 'NuTool-ClockConfig' isimli aracını kullanıyoruz. Pin konfigürasyonu ise, mikrodenetleyicinin hangi pinlerinin nasıl kullanılacağını belirler. Bu ayarlamaları da Nuvoton'un 'NuTool-PinConfig' isimli aracı ile gerçekleştiriyoruz.


Bu konfigürasyonlar ayarlandıktan sonra, mikrodenetleyicimizin PWM birimini belirli bir frekansta ve çözünürlükte bir PWM sinyali oluşturacak şekilde ayarlamamız gerekiyor. Bu uygulamada çözünürlüğün belirli bir değeri çok önemli olmayabilir ancak unutmayın ki çözünürlük, özellikle hassas kontrol gerektiren uygulamalarda son derece önemli olabilir.


Bu değerler doğru bir şekilde ayarlandığında, servo motorunuzu mikrodenetleyiciniz üzerinden kontrol edebilirsiniz. Şimdi, bu ayarları kodumuzda nasıl belirleyeceğimizi görmek için bir sonraki bölüme geçebiliriz. Sorularınız varsa yorumlar kısmından bana ulaşabilirsiniz. Haydi, kodlamaya başlayalım!


void PWM_Init(void)
{
// PWM0 kanal 2 için saat ayarları
PWM_SetClockSource(PWM0, 2, PWM_CLKSRC_PWM_CLK);

// Prescaler ve Counter ayarları
PWM_SET_PRESCALER(PWM0, 2, 0x3E7); // Prescaler değerini 999 olarak ayarlar
PWM_SET_CNR(PWM0, 2, 0x27F); // Counter değerini 639 olarak ayarlar

// Counter tipi ayarı
PWM0->CTL1 &= ~(0x3ul << 4 ); // Counter tipini belirler (Up-Counter)

// PWM0 Pulse Generator ayarları
PWM_SET_OUTPUT_LEVEL(PWM0, PWM_CH_2_MASK, PWM_OUTPUT_HIGH, PWM_OUTPUT_LOW, PWM_OUTPUT_NOTHING, 
                     PWM_OUTPUT_NOTHING); // PWM çıkış seviyesini ayarlar

// PWM0 kanal 2 çıkışını etkinleştir
PWM_EnableOutput(PWM0, PWM_CH_2_MASK);

// PWM0 kanal 2'yi başlat
PWM_Start(PWM0, PWM_CH_2_MASK);
}

Artık mikrodenetleyicimizin ve servo motorumuzun gerekli ayarlamalarını yaptığımıza göre, motorumuzu kontrol etmeye geçebiliriz. Bu aşamada, mikrodenetleyicimizi, servo motorumuzun belirli açılara dönebilmesi için gereken PWM sinyallerini oluşturacak şekilde programlayacağız.


Bu amaçla, PWM_SET_CMR() işlevini kullanarak servo motorun hangi açıya döneceğini belirleyeceğiz. Bu işlev, PWM sinyalinin duty cycle'ını, yani sinyalin ne kadar süreyle 'yüksek' (HIGH) durumunda kalacağını ayarlar. Servo motorumuz, bu 'yüksek' süresine göre hangi açıya döneceğini belirler.

Daha sonra, CLK_SysTickDelay() işlevi ile her bir açı değişikliği arasında belirli bir gecikme ekleyeceğiz. Bu sayede, servo motorumuzun her bir açı değişikliğinden sonra belirli bir süre beklemesini sağlarız. Bu süre boyunca, servo motorumuz, belirttiğimiz açıya dönecek ve bu pozisyonda kalacaktır.


Son olarak, bu işlemleri bir while (Nuvoton'un for döngüsne alerjisi var sanırım) döngüsü içinde gerçekleştireceğiz. Bu döngü, servo motorumuzun belirli bir açıdan başka bir açıya 'gidip gelmesini' sağlar. Bu sayede, servo motorumuzun farklı açılara dönebilme yeteneğini gösterebiliriz. Şimdi, bu kod parçalarını daha detaylı bir şekilde inceleyelim.


int main()
{
		// Baslangiç ve bitis noktalari
		int start = 16, end = 80;
		// Artis miktari
		int increment = 16;
	
		int pos = 0;
	
	SYS_Init();
	PWM_Init();
	
	while(1)
	{
		pos = start;
		
		// Start'tan end'e kadar hareket edin
		while(pos <= end)
		{
			// PWM0, kanal 2'nin CMR degerini ayarla (motorun pozisyonunu degistir)
			PWM_SET_CMR(PWM0, 2, pos);
			
			pos += increment;

			// Her dönüste 500 ms gecikme sagla
			CLK_SysTickDelay(500 * 1000);
		}

		pos = end;
		
		// End'den start'a geri dön
		while(pos >= start)
		{
			// PWM0, kanal 2'nin CMR degerini ayarla (motorun pozisyonunu degistir)
			PWM_SET_CMR(PWM0, 2, pos);
			
			pos -= increment;

			// Her dönüste 500 ms gecikme sagla
			CLK_SysTickDelay(500 * 1000);
		}
	}
}

Harika! Kodumuzu başarıyla yazdık ve gereken ayarlamaları tamamladık. Şimdi, tüm bu çabalarımızın meyvelerini toplama zamanı geldi. Hazırladığımız bu uygulamanın sonucunu aşağıdaki GIF animasyonunda görebiliriz.


Bu animasyonda, mikrodenetleyicinin oluşturduğu PWM sinyallerini kullanarak farklı açılara dönen SG90 servo motorumuzu gösteriyoruz. Göreceğiniz üzere, servo motorumuz belirttiğimiz açılara hassas bir şekilde dönebiliyor ve belirttiğimiz süre boyunca bu pozisyonlarda kalabiliyor.


Evet, işte karşınızda, kodlarımızla hayat verdiğimiz SG90 servo motorumuz!


Ne mutlu ki birlikte keyifli bir uygulamayı tamamlamış olduk. SG90 servo motorunun kontrolü, mikrodenetleyiciler ve donanım arasındaki etkileşim konusunda daha fazla bilgi sahibi olmamızı sağladı. Umarım bu yazı, sizin de benzer projelere başlamanızda bir başlangıç noktası olmuştur.


Kullandığımız tüm kodları GitHub hesabımda paylaşıyorum. Kodları inceleyebilir, kendi projelerinizde kullanabilir, hatta üzerinde değişiklikler yapabilirsiniz. Unutmayın, pratik yapmak öğrenmenin en iyi yoludur.


Her zaman olduğu gibi, herhangi bir sorunuz veya daha fazla bilgiye ihtiyacınız olursa yorumlar kısmında benimle iletişime geçebilirsiniz. Yeni bir projede görüşmek dileğiyle.


Kahve-Gece-Kodlama üçgeninde başarılar sizi bekliyor!


 
 
 

Comments


bottom of page