Servo senkronizasyon modülü

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.

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();
  }
}
 
Servo senkronizasyon modülü

Sümer Yamaner' Alıntı:
..... 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.
Abi evde Osiloskop var demeyeceksin değil mi ??
 
Ama bu iş için aslında osiloskop da şart değil. Bir başka Arduino Uno ya da Nano kısa bir program ile darbe süresi ya da frekansı ölçecek şekilde kullanılabilir. Bak bunu niye düşünmedim ki ben? :)
 
Servo senkronizasyon modülü

Sümer Yamaner' Alıntı:
Ama bu iş için aslında osiloskop da şart değil. Bir başka Arduino Uno ya da Nano kısa bir program ile darbe süresi ya da frekansı ölçecek şekilde kullanılabilir. Bak bunu niye düşünmedim ki ben? :)
Kesinlikle abi, artık devir Arduino devri, osiloskop da neymiş :lol:
 
Azıcık Visual Basic ile de uğraşabilsem Arduino'dan USB üzerinden gelen değerleri grafik olarak gösterecek basit bir PC osiloskop da yapardım ne güzel. :(
 
Tuşları okumak için şu alt programı hazırladım. Ancak tuş okurken bazen saçmalıyor. Tek sefer basıyorum ama birkaç tık atlıyor kimi zaman. Gece geç vakitte kalın yazılı kısmı ekledim koda. Beklediğim etkiyi elde edebilirsem tuş kontrolü de halledilmiş olacak.

Kod:
int keypress() // 0: Geçerli tuş yok. 1: Mode1. 2: Mode2. 3: Decrease. 4: Increase. 5: Done.
{
  int flag1 = 0;
  int flag2 = 0;
  int result = 0;

  int pressed1 = 1;
  int pressed2 = 1;
  int pressed3 = 1;
  int pressed4 = 1;
  
  int test = 4;

[b]  while(test < 4) // Başta herhangi bir tuşa basılmıyor olmalı. Bu durumda test değişkeninin değeri 4 olur. Yani test=4 olana kadar bekliyoruz.
  {
    pressed1 = digitalRead(mode1);
    pressed2 = digitalRead(mode2);
    pressed3 = digitalRead(decrease);
    pressed4 = digitalRead(increase);
    test = pressed1 + pressed2 + pressed3 + pressed4;
  }
  [/b]
  pressed1 = digitalRead(mode1);
  pressed2 = digitalRead(mode2);
  pressed3 = digitalRead(decrease);
  pressed4 = digitalRead(increase);
  
  delay(20); // Debounce için
  
  pressed1 = pressed1 + digitalRead(mode1);
  pressed2 = pressed2 + digitalRead(mode2);
  pressed3 = pressed3 + digitalRead(decrease);
  pressed4 = pressed4 + digitalRead(increase);
  
  if(pressed1 > 1) pressed1 = 1;
  if(pressed2 > 1) pressed2 = 1;
  if(pressed3 > 1) pressed3 = 1;
  if(pressed4 > 1) pressed4 = 1;  


  if ((pressed1 == 0) && (pressed2 == 0) && (pressed3 == 1) && (pressed4 == 1)) // Save & Exit tuşu
  {
    for (int i = 0; i < 60; i = i + 2)
    {
      if (digitalRead(mode1) == 1) return (0);
      if (digitalRead(mode2) == 1) return (0);
      delay(50);
    }
    return (5);
  }

  if (pressed1 != pressed2) flag1 = 1;
  if (pressed3 != pressed4) flag2 = 1;

  if (flag1 == flag2) return (0);

  if (pressed1 == 0) return (1);
  if (pressed2 == 0) return (2);
  if (pressed3 == 0) return (3);
  if (pressed4 == 0) return (4);
}
 
Servo senkronizasyon modülü

Sümer Yamaner' Alıntı:
Abicim basit bir LCD ekranlı, çift kanal, 30 MHz osiloskop tabii var. Onsuz ne yaparım ben? :D

Yok artık ... :D :lollol: :D .
 
Servo senkronizasyon modülü

Sümer Yamaner' Alıntı:
Abicim basit bir LCD ekranlı, çift kanal, 30 MHz osiloskop tabii var. Onsuz ne yaparım ben? :D

Niye bu kadar şaşırdınız anlamadım. Her doktorda illaki bir stetoskop vardır, ciddi ciddi osiloskop olacak hali yok ya biraz mantık kullanarak okuyunca anlaşılıyor hemen.

Yazım hatası (maddi hata) olmuştur, insanllık halidir olur. Yoksa bizim elektronik atölyede bile olmayan osiloskopun bir genel cerrahta ne işi var, ilahiler sizi. :lol: :lol: :lol:
 
Osiloskop benim gençlik dönemimdeki hayallerimden biriydi. Almanya kökenli ELO ve Funkschau adlı iki muhteşem elektronik dergisini buldukça alırdım. Birkaç Funkschau sayısında seri halinde bir osiloskop şeması yayımlanmıştı. Senelerce o şemaları incelediğimi bilirim. :D Sonunda imkanlar elverince on sene kadar önce bir osiloskop almam mümkün oldu. Şunu kullanıyorum:

Ahım şahım bir alet olmasa da işimi görüyor. :D
 
Servo senkronizasyon modülü

Türker Akgün' Alıntı:
Niye bu kadar şaşırdınız anlamadım. Her doktorda illaki bir steteskop vardır, ciddi ciddi osiloskop olacak hali yok ya biraz mantık kullanarak okuyunca anlaşılıyor hemen.

Yazım hatası (maddi hata) olmuştur, insanllık halidir olur. Yokda bizim elektronik atölyede bile olmayan osiloskopun bir genel cerrahta ne işi var ilahiler sizi. :lol: :lol: :lol:

Tabii canıımmm... Stetoskopu Atmega328'in üzerine tutunca tıklamaları duyuyorsun zaten. :p :D
 
Servo senkronizasyon modülü

Şu kod bende standart olabilir artık:

Kod:
int senspin = 0;
volatile int pwm = 1500;
volatile int servopin = 5;
volatile unsigned long timer;
volatile int x = 0;


void setup() {
  pinMode(servopin, OUTPUT);
  timerinit();
}

void loop()
{
  pwm = 1000 + analogRead(senspin);
}

void timerinit()
{
  // initialize Timer1
  noInterrupts();  // disable global interrupts
  TCCR2A = 0;
  TCCR2B = 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)
{
  x++;
  if(x > 4) // 4 olursa 20.5 mS, 5 olursa 24.6 mS PPM frame
/* Burada hesap şöyle: I/O CLK 16 MHz
   Prescaler ile bölünüyor
   16000000 / 256 = 62500 Hz
   Timer Counter 2 ile bir kez daha 256'ya bölünüyor
   62500 / 256 = 244.14 Hz
   x için sınırı 4 dersek, 0'dan 5'e kadar sayılması gerekli.
   Yani frekans 5'e bölünüyor
   244.14 / 5 = 48.83 Hz
   Bunun periyodu 1 / 48.83 = 20.48 mS
*/  
  {
    x = 0;
    timer = micros();
    digitalWrite(servopin, HIGH);
    while ((micros() - timer) < pwm)
    {
    }
    digitalWrite(servopin, LOW);
  }
}

Bu değerler ile servo sürmek için tam 20.5 mS frame elde ediliyor.
 
Servo senkronizasyon modülü

Sümer abi senin yüzünden bugün ben de oturdum Timer okumaya başladım... Ne gerek vardı şimdi mis gibi servo kütüphanesi varken :'( ...
 
Servo senkronizasyon modülü

Basit işlevler (reverser, slover, v tail mikser gibi) için koskoca bir Arduino kartı değil ATtiny85 kullanmak çok mantıklı. Hem maliyet hem de boyut çok azalıyor. Ama işin içine servo output girdiğinde interrupt ve timer kaçınılmaz oluyor. Hazır library'ler ise belirli kartları şart koşuyor. Başka birinin kafasına göre yazdığı bir kütüphane kullanıp onun kuralları ile çalışmak yerine kendi kuralımızı kendimiz koyuyoruz bu şekilde. :D
Her ne kadar "benim yüzümden" de olsa böyle hayırlı bir işe vesile olmaktan mutlu oldum! :D :D :D
Ben "senin yüzünden" ne durumdayım bir de ona baksan!!! :lol:
 
Servo senkronizasyon modülü

Her ikinizde aksam aksam beni güldürdünüz ya, Allah da sizi güldürsün :) :)


Sent from my iPhone using Tapatalk