Yeni Proje: Servolu jikle koruması

Yeni Proje: Servolu jikle koruması

Mustafa Çoban.' Alıntı:
Abi sen de bişeyler yapmıyorum diye utanıyorsan benim gibi hazırcılar ne yapması lazım anlamadım. :saygilar:
Tevazu sahibi abimiz bizim, keske herkes senin gibi olabilse :bravo: :thumbup:
 
Yeni Proje: Servolu jikle koruması

Projeyi en küçük mikroişlemcilerden olan Attiny85 bazında gerçekleştirmek için uğraşıyorum. Attiny85'de tek harici interrupt olduğu için Pin Change Interrupt olayına girdim. Yazılımı önce Arduino UNO'da ama Pin Change Interrupt kullanarak yani aslında işlemcinin ciğerine doğrudan müdahale ederek denedim. Mükemmel oldu. Şimdi kodu Attiny85'e adapte edip devreyi yapmak kaldı.
Arduino kodu:

Kod:
//Motor çalışırken jikle aktivasyonunu önleyen program
//Atmega328 versiyonu
/*
ADC3, Analog in
INT0, Alıcıdan PWM girişi (PB2)
PCINT1, RPM sensör girişi (PB11)
PB0, Servo çıkışı
PB4, Buton girişi
*/

const int sensorpin = 11; // Ateşleme sensörü girişi
const int pwmpin = 2; // Alıcıdan gelen jikle kanalı sinyali girişi
const int servopin = 0; // Jikle servosu çıkışı
const int setpospin = 3; // Trimpot ile jikle OFF servo konumu ayarlanıyor A3
const int buton = 4; //Buton pini PB4

// Interruptlar sırasında değiştirilecek olan değişkenler
volatile unsigned long xpwm1;
volatile unsigned long xpwm2;
volatile unsigned long xrpm1;
volatile unsigned long xrpm2;

// Normal işleyişte kullanılacak değişkenler
unsigned long pwm1;
unsigned long pwm2;
unsigned long rpm1;
unsigned long rpm2;

// Yardımcı değişkenler
volatile byte pflag = 0;
volatile byte temp = 0;
unsigned long frame;

// Temel parametreler
unsigned long period; // Motor devir periyodu
unsigned int pwm; // Alıcıdan gelen darbe süresi
unsigned int servopwm; // Servoya gidecek darbe süresi
unsigned int offvalue; // Jikle OFF konumunu içeren değişken

byte sregvalue;

void setup()
{
  pinMode(servopin, OUTPUT);
  pinMode(buton, INPUT_PULLUP);
  offvalue = 1000 + analogRead(setpospin); // Jikle OFF konumu için belirlenen servo pozisyonu okunuyor
  attachInterrupt(0, pwmread, CHANGE); // Alıcı sinyalini okumak için
//  GIMSK |= B00100000; // Pin Change Interrupt Enable Attiny85
//  PCMSK |= B00000010; // Pin Change Interrupt on pin PB1 Attiny85
  PCICR |= B00000001; // Pin Change Interrupt Enable Atmega
  PCMSK0 |= B00001000; // Pin Change Interrupt on digital pin 3 Atmega
}

void loop()
{
  if (digitalRead(buton) == 0)
  {
    setservo();
  }
  else
  {
    while (pflag == 0) // Alıcıdan yeni bir sinyal gelene kadar bekliyoruz
    {
    }
    noInterrupts(); // Atomic read
    pwm1 = xpwm1;
    pwm2 = xpwm2;
    rpm1 = xrpm1;
    rpm2 = xrpm2;
    interrupts();

    if (pwm2 >= pwm1) pwm = pwm2 - pwm1; // PWM pulse süresi hesabı
    if (rpm2 < rpm1) period = rpm1 - rpm2; // RPM pulse süresi hesabı
    if (period < 120000) // Motor devri 500'den fazla ise
    {
      servopwm = offvalue;
    }
    else // Motor devri 500'den az ise
    {
      servopwm = pwm;
    }
    servoout();
    pflag = 0;
  }
}

void pwmread() // Alıcı sinyalini okuyan interrupt işlevi
{
  sregvalue = SREG;
  temp = digitalRead(pwmpin);
  if (temp == 1) xpwm1 = micros();
  if (temp == 0)
  {
    xpwm2 = micros();
    pflag = 1;
  }
  SREG = sregvalue;
}

ISR(PCINT0_vect) // Motor devrini okuyan interrupt işlevi
{
  sregvalue = SREG;
  interrupts();
  if (digitalRead(sensorpin) == 1)
  {
    xrpm2 = xrpm1;
    xrpm1 = micros();
  }
  SREG = sregvalue;
}


void servoout() // Jikle servosuna çıkış veren işlev
{
  noInterrupts();
  digitalWrite(servopin, HIGH);
  delayMicroseconds(servopwm);
  digitalWrite(servopin, LOW);
  interrupts();
}

void setservo()
{
  noInterrupts();
  offvalue = 1000 + analogRead(setpospin); // Jikle OFF konumu için belirlenen servo pozisyonu okunuyor
  servopwm = offvalue;
  frame = micros();
  servoout();
  while ((micros() - frame) < 20000)
  {
  }
  interrupts();
}

Attiny85 kodu:

Kod:
//Motor çalışırken jikle aktivasyonunu önleyen program
//Attiny85 versiyonu
/*
Attiny85 pin 2 -> ADC3, Analog in
Attiny85 pin 7 -> INT0, Alıcıdan PWM girişi (PB2)
Attiny pin 6 -> PCINT1, RPM sensör girişi (PB1)
Attiny pin 5 -> PB0, Servo çıkışı
Attiny pin 3 -> PB4, Buton girişi
*/

const int sensorpin = 1; // Ateşleme sensörü girişi
const int pwmpin = 2; // Alıcıdan gelen jikle kanalı sinyali girişi
const int servopin = 0; // Jikle servosu çıkışı
const int setpospin = 3; // Trimpot ile jikle OFF servo konumu ayarlanıyor A3
const int buton = 4; //Buton pini PB4

// Interruptlar sırasında değiştirilecek olan değişkenler
volatile unsigned long xpwm1;
volatile unsigned long xpwm2;
volatile unsigned long xrpm1;
volatile unsigned long xrpm2;

// Normal işleyişte kullanılacak değişkenler
unsigned long pwm1;
unsigned long pwm2;
unsigned long rpm1;
unsigned long rpm2;

// Yardımcı değişkenler
volatile byte pflag = 0;
volatile byte temp = 0;
unsigned long frame;
byte portread;

// Temel parametreler
unsigned long period; // Motor devir periyodu
unsigned int pwm; // Alıcıdan gelen darbe süresi
unsigned int servopwm; // Servoya gidecek darbe süresi
unsigned int offvalue; // Jikle OFF konumunu içeren değişken

byte sregvalue;

void setup()
{
  pinMode(servopin, OUTPUT);
  pinMode(buton, INPUT_PULLUP);
  offvalue = 1000 + analogRead(setpospin); // Jikle OFF konumu çin belirlenen servo pozisyonu okunuyor
  attachInterrupt(0, pwmread, CHANGE); // Alıcı sinyalini okumak için
  GIMSK |= B00100000; // Pin Change Interrupt Enable Attiny85
  PCMSK |= B00000010; // Pin Change Interrupt on pin 6 Attiny85
}

void loop()
{
  if (digitalRead(buton) == 0)
  {
    setservo();
  }
  else
  {
    while (pflag == 0) // Alıcıdan yeni bir sinyal gelene kadar bekliyoruz
    {
    }
    noInterrupts(); // Atomic read
    pwm1 = xpwm1;
    pwm2 = xpwm2;
    rpm1 = xrpm1;
    rpm2 = xrpm2;
    interrupts();

    if (pwm2 >= pwm1) pwm = pwm2 - pwm1; // PWM pulse süresi hesabı
    if (rpm2 < rpm1) period = rpm1 - rpm2; // RPM pulse süresi hesabı
    if (period < 120000) // Motor devri 500'den fazla ise
    {
      servopwm = offvalue;
    }
    else // Motor devri 500'den az ise
    {
      servopwm = pwm;
    }
    servoout();
    pflag = 0;
  }
}

void pwmread() // Alıcı sinyalini okuyan interrupt işlevi
{
  sregvalue = SREG;
  temp = digitalRead(pwmpin);
  if (temp == 1) xpwm1 = micros();
  if (temp == 0)
  {
    xpwm2 = micros();
    pflag = 1;
  }
  SREG = sregvalue;
}

ISR(PCINT0_vect) // Motor devrini okuyan interrupt işlevi
{
  sregvalue = SREG;
  interrupts();
  portread = PORTB & B00000010;
  if (portread > 0)
  {
    xrpm2 = xrpm1;
    xrpm1 = micros();
  }
  SREG = sregvalue;
}


void servoout() // Jikle servosuna çıkış veren işlev
{
  noInterrupts();
  digitalWrite(servopin, HIGH);
  delayMicroseconds(servopwm);
  digitalWrite(servopin, LOW);
  interrupts();
}

void setservo()
{
  noInterrupts();
  offvalue = 1000 + analogRead(setpospin); // Jikle OFF konumu çin belirlenen servo pozisyonu okunuyor
  servopwm = offvalue;
  frame = micros();
  servoout();
  while ((micros() - frame) < 20000)
  {
  }
  interrupts();
}
 
Yeni Proje: Servolu jikle koruması

Şöyle de bir plaketimiz var...

[attachimg=1]

Cuma günkü sunumuma hazırlanıyorum. Bunu plakete döküp kutulayıp kullanılır hale getirmek için Cumartesi'yi planladım. İnşallah Pazar günü sahada testini videoya çekip paylaşırım.
 

Ekli dosyalar

  • Untitled.jpg
    Untitled.jpg
    58.9 KB · Görülme: 111
Yeni Proje: Servolu jikle koruması

Test videosunu merakla bekliyoruz abi :halay:


Sent from my iPhone using Tapatalk
 
Yeni Proje: Servolu jikle koruması

Proje ile ilgili biraz teknik detay yazayım. Okunsun diye değil de dokümantasyon tam olsun diye yazıyorum. :)

Bu proje, biraz sürüncemede kalan rölanti koruma projesine ışık tutacak birçok gelişmeye sahne oldu. Hemen her gün yeni bir kod vrsiyonu üretip test ediyorum. Uygulamadaki temel sorunları şu şekilde özetleyebilirim:
- Her 20 mS'de bir gelen alıcı sinyalinin hatasız okunması
- Her 20 mS'de bir servoya hatasız sinyal gönderilmesi
- Ne kadar zamanda bir geleceği belli olmayan ateşleme sinyalinin aralığının elden geldiğince hatasız ölçülmesi
Dikkat edilirse bu üç işlevin sürekli ve aynı anda yapılması gerekiyor.
Diğer yandan bu kadar basit bir iş için koskoca bir Arduino kartını harcamak da içime sinmiyor. Tabii ilk uygulamaları Arduino Uno kartı ile yapıp kodun temelini oturtmam gerekiyordu. Ama kod artık Attiny denilen 8 bacaklı mikroişlemciye uygun hale getirildi.
Bu amaçla, mikroişlemcinin "Pin Change Interrupt" adı verilen özelliği kullanılıyor. Bizim belirleyeceğimiz pinlerde oası bir değişim bir interrupt'ı tetikliyor. Daha anlaşılır bir şekilde söylemek gerekirse, ben iki pini seçtim. Biri alıcıdan gelen sinyal diğeri ateşlemeden gelen sinyal. Mikroişlemci her ne yapıyor olursa olsun, bu iki sinyalden biri ya da ikisi değiştiğinde işlemci yaptığı işi bırakıp ayrı bir programa yönleniyor. Bu ayrı program (buna Interrupt servis rutini ISR diyoruz) Arduino sisteminin komutlarını kullanmak yerine mikroişlemcinin ilgili pinlerini doğrudan okuyor. Yani birkaç döngü yerine tek döngüde veriyi almış oluyor. Sonra bu veriyi işliyor. Her durumda en az bir milisaniye zamanı var ki bu mikroişlemci için çok uzun bir süre. Burada hangi uçta değişim olduğu, değişimin 1'den 0'a mı yoksa 0'dan 1'e mi olduğu belirleniyor ve sistemin mikrosaniye hassasiyetindeki sayacının konumu farklı değişkenlere aktarılıyor. İşte bu yaklaşımla artık asenkron olarak gelen iki farklı sinyalin sürelerinin eşzamanlı ve hatasız (belki birkaç mikrosaniye hata ile) okunması mümkün oluyor.
Bu sistemi bu akşam oturtup test ettim. Gerçekten de çok güzel çalıştı. Özellikle servo titremesi sorunu ortadan kalktı. Artık, buradan edindiğim deneyim ve bilgi ile yarıda kalmış olan rölanti koruma devresine de geri dönmem mümkün olacak.
Bir yandan da etraftan proje önerileri yağmaya devam ediyor. Biraz nefes aldığımda sıra LED göstergeli, akım sensörlü, süre sınırlamalı bir buji kızdırıcı yapmam gerekecek. :)
 
Yeni Proje: Servolu jikle koruması

Abi sen bu kadar hassas calisip muhtesem isler cikardikca yeni taleplerin sonu gelmeyecektir :laugh: :D
 
Yeni Proje: Servolu jikle koruması

Minik jikle servosu koruma modülümüz hazır. Test edildi. Onaylandı. Şu an titreşim ve korozyon koruması amaçlı uyguladığım sıvı elektrik bandı kuruyor. Birazdan kutusuna girecek ve kullanıma hazır olacak.

[attachimg=1]

[attachimg=2]
 

Ekli dosyalar

  • pic0001.jpg
    pic0001.jpg
    60.9 KB · Görülme: 80
  • pic0001_001.jpg
    pic0001_001.jpg
    54.5 KB · Görülme: 80
Yeni Proje: Servolu jikle koruması

Ve nihaî ürün... :D

[attachimg=1][attachimg=2]
 

Ekli dosyalar

  • pic0001.jpg
    pic0001.jpg
    71.8 KB · Görülme: 75
  • pic0002.jpg
    pic0002.jpg
    60.5 KB · Görülme: 75
Yeni Proje: Servolu jikle koruması

Abi hayırlı olsun bir projeyi daha tamamlamış oldun hızına yetisemiyoruz maşallah Allah nazarlardan korusun :saygılar:
 
Yeni Proje: Servolu jikle koruması

Sümer Yamaner' Alıntı:
Ve nihaî ürün... :D
Veee bir proje daha başarılı bir şekilde sonuçlanır :halay: Kutusu falan çok hoş olmuş abi, ellerine sağlık :)
 
Yeni Proje: Servolu jikle koruması

Sumer abim uzun suredir ses alamiyoruz senden ?? Son durumlar nedir ? Hangi yeni proje gundemde :thumbup:
 
Yeni Proje: Servolu jikle koruması

Durumlar çok karışık. İşler yoğun. Kongreler art arda geliyor. Konuşmalar hazırlanıyor. Ben de bu durumdan rahatsızım.
Geçen haftaki son uçuş gününde ESM Sea Fury resmen dağıldı! :D Tam bir sene oluyordu ve doğal olarak büyük bakım zamanı gelmişti. Yakıt deposunun boynu çatlamış, burundaki ağırlık firewalldan neredeyse ayrılacakmış. Ateşleme modülü özgürlüğünü ilan etmiş. Onu eve getirip büyük bakımını yapınca başka bir şeye vakit kalmadı doğal olarak.
Jikle korumanın saha testini büyük olasılıkla yarın yapacağız. Umarım video çekebilirim. İşin ilginci aynı uçakta bir de servo senkronizatörü görev yapacak. Uçak da Edge 540 55 cc! Yani yarın benim için sınav günü! :)
Bu arada iki gündür rölanti koruma devresine döndüm. Birkaç plaket yapıp denemeler yaptım. Servodaki huzursuzluğu gideremiyorum bir türlü. Az önce Arduino forumlarına detaylı olarak yazdım. Bakalım belki bir yol gösteren çıkar.
Kısaca durum budur, arzolunur! :D
 
Yeni Proje: Servolu jikle koruması

Sümer abi , Sea Fury dağılmış resmen dediğinde hoplattın bir an :rolleyes: , ben de Allah korusun kırım yaptın zannettim. :)...Tabi , nerdeyse bir yıl oldu , tornacıda özel olarak yaptırdığın o kocaman ağırlık , iyi bile dayanmış...Neyse ki modelin sağlam bir doktoru var :thumbup: , yarın uçuş varsa , video da olacak demektir.. :halay: İnşallah , jikle koruma işini hakkıyla yapar , biz de güzel uçuşlar seyrederiz.... :saygilar:
 
Yeni Proje: Servolu jikle koruması

Bauhaus'tan bir tarafı ağaç vidası diğer tarafı cıvata gibi olan M6 saplamalar almıştım bu iş için. Çift taraflı bant desteği ile ve fiberli somunlarla (üç adet) tespit etmiştik. Hatta burada fotoğrafları da olması lazım. Üst ve alttaki saplama ağaç vidası tarafından firewall'dan çıkıp havada düşmüş. Ne zaman düştüler bilmiyorum. Ortadaki de düştü düşecek haldeymiş. Allah'tan ağırlık motor bacaklarına dayandığı için yerinden kurtulmamış. Yoksa havadan kafamıza 1.5 kg demirin düştüğünü düşünsene!!! Kafamıza düşmese bile uçak havada öyle bir şahlanırdı ki kimse kurtaramazdı!
Bu sefer M6 cıvata ve çiftli fiberli somunlarla çok sağlam tespit ettim. Ayrıca poliüretan yapıştırıcı ile de destekledim. Bundan sonra ancak firewall ile birlikte çıkar yerinden. :D :p
Bu arada cowling montaj deliklerinin arkalarına destek ahşapları yapıştırdım binbir cambazlıkla. Cowlingin ufak sorularını giderdim. Ama asıl önemlisi atlattığım büyük tehlike idi. Ağırlığın deliklerini 6 mm matkap ile büyütmem gerekiyordu. Balkonda giriştim işe. Arkada iki adet 2S 2200 mAh LiFe olduğunu unutmuşum! :( Bir anda duman çıkmaya başladı. Allah'tan geçen yıl LiPo'ları LiFe ile değiştirmiştim. Yoksa şu an uçak yoktu. Ev de olmayabilirdi!!! :(
Acele işe şeytan karışıyor gerçekten de.
 
Yeni Proje: Servolu jikle koruması

Sümer Yamaner' Alıntı:
Bauhaus'tan bir tarafı ağaç vidası diğer tarafı cıvata gibi olan M6 saplamalar almıştım bu iş için. Çift taraflı bant desteği ile ve fiberli somunlarla (üç adet) tespit etmiştik. Hatta burada fotoğrafları da olması lazım. Üst ve alttaki saplama ağaç vidası tarafından firewall'dan çıkıp havada düşmüş. Ne zaman düştüler bilmiyorum. Ortadaki de düştü düşecek haldeymiş. Allah'tan ağırlık motor bacaklarına dayandığı için yerinden kurtulmamış. Yoksa havadan kafamıza 1.5 kg demirin düştüğünü düşünsene!!! Kafamıza düşmese bile uçak havada öyle bir şahlanırdı ki kimse kurtaramazdı!
Bu sefer M6 cıvata ve çiftli fiberli somunlarla çok sağlam tespit ettim. Ayrıca poliüretan yapıştırıcı ile de destekledim. Bundan sonra ancak firewall ile birlikte çıkar yerinden. :D [emoji14]
Bu arada cowling montaj deliklerinin arkalarına destek ahşapları yapıştırdım binbir cambazlıkla. Cowlingin ufak sorularını giderdim. Ama asıl önemlisi atlattığım büyük tehlike idi. Ağırlığın deliklerini 6 mm matkap ile büyütmem gerekiyordu. Balkonda giriştim işe. Arkada iki adet 2S 2200 mAh LiFe olduğunu unutmuşum! :( Bir anda duman çıkmaya başladı. Allah'tan geçen yıl LiPo'ları LiFe ile değiştirmiştim. Yoksa şu an uçak yoktu. Ev de olmayabilirdi!!! :(
Acele işe şeytan karışıyor gerçekten de.
Abi geçmiş olsun pil işi gerçekten sakat dikkatsizliğe gelmiyor.