- Katılım
- 17 Eyl 2013
- Mesajlar
- 9,084
- Tepkime puanı
- 23,743
- Yaş
- 62
- Konum
- İstanbul
- Web sitesi
- www.sumeryamaner.com
- İlgi Alanı
- Uçak
Servo senkronizasyon modülü
Servo çıkış sinyalinin yaklaşık her 20 mS'de bir üretilebilmesi için MsTimer2 kütüphanesini kullanmıştım ama neden olduğunu anlayamadığım bir şekilde sistem kilitleniyordu. Bunun üzerine doğrudan timer ve interrupt sistemine müdahale etmeye karar verdim. Timer 0 Arduino IDE'nin işlevleri için kullanılıyor. Timer1 ise 16 bit yani kullanımı biraz daha zahmetli. Timer2 hem standart bir işlev için kullanılmıyor hem de 8 bit. Aşağıdaki kod parçası ile (timerinit) 16 MHz sistem saati 256'ya bölünüyor. Yani 62.5 kHz oluyor. Timer2 bu sinyali sayıyor. Sıfırdan 255'e kadar sayıp "overflow" olunca interrupt üretiyor. Interrupt frekansı yaklaşık 245 Hz oluyor bu şekilde. Interrupt servis rutininde ise kaç kez çağrıldığı sayılıyor. Beş kez olduysa servolara çıkış veriliyor (servoout). Yani 245 / 5 = 49 Hz oluyor ki istenen 50 Hz değerine çok yakın. Bu hali ile herhangi bir sorun olmadan her türlü servo çalıştırılabiliyor.
Bu sadece bu uygulamanın değil, bundan sonra yapılacak tüm servo çıkışlı projelerin temel sinyal üretim kodu olacak.
Kafamda şöyle bir soru işareti var. ATmega328 işlemcinin datasheet'ini alt üst ettim. Forumlara baktım. Timer'ların besleme frekansı konusunda net bilgi yok. Yani benim en başta 256'ya böldüğüm değer gerçekten 16 MHz mi yoksa daha düşük bir değer mi emin olamadım. Ama dün akşamki testlerde interrupt servis rutini içindeki sayacı beş değil de 2 ya da 3 yaptığımda (yani 80 - 120 Hz) servonun çok daha güzel tepk verdiğini gördüm. Normalde bir analog servoya (en dandiğini kullandım testte) 20 mS'den daha düşük aralıkla sinyal gitmesi halinde servo sapıtır ve ısınır. Ama benim testimde 120 Hz ayarında bile sorun olmadı. Bu da bende yukarıda yapmış olduğum hesaplamalar konusunda şüphe uyandırıyor. Bu akşamki planların birisi osiloskop ekranında servo çıkış sinyalini kontrol edip hassas timing ayarını belirlemek ve bu kodu artık tüm projeler için temel kod olarak kayda almak.
Servo çıkış sinyalinin yaklaşık her 20 mS'de bir üretilebilmesi için MsTimer2 kütüphanesini kullanmıştım ama neden olduğunu anlayamadığım bir şekilde sistem kilitleniyordu. Bunun üzerine doğrudan timer ve interrupt sistemine müdahale etmeye karar verdim. Timer 0 Arduino IDE'nin işlevleri için kullanılıyor. Timer1 ise 16 bit yani kullanımı biraz daha zahmetli. Timer2 hem standart bir işlev için kullanılmıyor hem de 8 bit. Aşağıdaki kod parçası ile (timerinit) 16 MHz sistem saati 256'ya bölünüyor. Yani 62.5 kHz oluyor. Timer2 bu sinyali sayıyor. Sıfırdan 255'e kadar sayıp "overflow" olunca interrupt üretiyor. Interrupt frekansı yaklaşık 245 Hz oluyor bu şekilde. Interrupt servis rutininde ise kaç kez çağrıldığı sayılıyor. Beş kez olduysa servolara çıkış veriliyor (servoout). Yani 245 / 5 = 49 Hz oluyor ki istenen 50 Hz değerine çok yakın. Bu hali ile herhangi bir sorun olmadan her türlü servo çalıştırılabiliyor.
Bu sadece bu uygulamanın değil, bundan sonra yapılacak tüm servo çıkışlı projelerin temel sinyal üretim kodu olacak.
Kafamda şöyle bir soru işareti var. ATmega328 işlemcinin datasheet'ini alt üst ettim. Forumlara baktım. Timer'ların besleme frekansı konusunda net bilgi yok. Yani benim en başta 256'ya böldüğüm değer gerçekten 16 MHz mi yoksa daha düşük bir değer mi emin olamadım. Ama dün akşamki testlerde interrupt servis rutini içindeki sayacı beş değil de 2 ya da 3 yaptığımda (yani 80 - 120 Hz) servonun çok daha güzel tepk verdiğini gördüm. Normalde bir analog servoya (en dandiğini kullandım testte) 20 mS'den daha düşük aralıkla sinyal gitmesi halinde servo sapıtır ve ısınır. Ama benim testimde 120 Hz ayarında bile sorun olmadı. Bu da bende yukarıda yapmış olduğum hesaplamalar konusunda şüphe uyandırıyor. Bu akşamki planların birisi osiloskop ekranında servo çıkış sinyalini kontrol edip hassas timing ayarını belirlemek ve bu kodu artık tüm projeler için temel kod olarak kayda almak.
Kod:
void timerinit()
{
// initialize Timer2
noInterrupts(); // disable global interrupts
TCCR2A = 0;
// prescaler 256
TCCR2B |= (0 << CS20);
TCCR2B |= (1 << CS21);
TCCR2B |= (1 << CS22);
TCNT2 = 0;
TIMSK2 |= (1 << TOIE2);
// enable global interrupts
interrupts();
}
ISR(TIMER2_OVF_vect)
{
intcounter++;
if(intcounter > 5);
{
intcounter = 0;
servoout();
}
}