Gerçek lövye ile model uçurmak

Gerçek lövye ile model uçurmak


Sümer Yamaner' Alıntı:
Abi bu baya baya uçuyor :D

Saka bir yana abi kalkış da iniş de harika, ellerine saglık :halay:


Sent from my iPhone using Tapatalk
 
Gerçek lövye ile model uçurmak

Sümer abi gerçekten elinize sağlık, herşeyiyle harika olmuş. İlk gerçek uçuş videosunu heyecanla bekliyorum. :)
 
Gerçek lövye ile model uçurmak

Bugün çok önemli bir şey daha öğrendim. PPM sinyalini ben birbirinden 300 mikrosaniyelik aralıklarla ayrılmış 1000 - 2000 mikrosaniye arası darbelerden oluşur sanıyordum. Halbuki darbeden sonraki 300 mikrosaniye de darbe süresine dahilmiş. Yani 2000 mikrosaniyelik sinyal 1700 mikrosaniye HIGH, 300 mikrosaniye LOW şeklinde oluşturuluyormuş. Tabii tüm kodu buna göre elden geçirip düzenledim. :)
 
Gerçek lövye ile model uçurmak

Arşiv amaçlı en son versiyon kodu buraya yazıyorum.

Kod:
/* Uçuş alanında kullanılacak lövye sistemi için program
   Aileron A0
   Elevatör A1
   Throttle A2
   Rudder A3

   Aileron trim left D2
   Aileron trim right D3
   Elevatör trim down D4
   Elevatör trim up D5
   Rudder trim left D6
   Rudder trim right D7
   Throttle trim down D8
   Throttle trim up D9

   Kanal 5 D11
   Kanal 6 D12



   PPM çıkışı D10

   Elevator Down ve Throttle Up trimlerini birlikte 3 saniye
   basılı tutunca tüm trimler sıfırlanıyor

   Elevator Up ve Throttle down trimlerini birlikte 3 saniye
   basılı tutunca çıkış sinyali invert oluyor
*/

#include <EEPROM.h>

const int aileronin = 0;
const int elevatorin = 1;
const int throttlein = 2;
const int rudderin = 3;

const int PPMout = 10;
const int LED = 13;

const int aileronleft = 2;
const int aileronright = 3;
const int elevatordown = 4;
const int elevatorup = 5;
const int rudderleft = 6;
const int rudderright = 7;
const int throttledown = 8;
const int throttleup = 9;

const int ch5in = 11;
const int ch6in = 12;

// Donanımsal verilere göre elde edilen endpointler.
const int a1 = 123;
const int a2 = 786;
const int e1 = 172;
const int e2 = 838;
const int t1 = 0;
const int t2 = 1023;
const int r1 = 293;
const int r2 = 481;

// Donanımın sunduğu hareket alanları
int a;
int e;
int t;
int r;

const int atva = 100; // Aileron travel percentage
const int etva = 100; // Elevator travel percentage
const int rtva = 100; // Rudder travel percentage

// Throttle endpointleri modele göre belirlenecek
unsigned int epa1 = 0;
unsigned int epa2 = 1000;

unsigned long frame1;
unsigned long frame2;
unsigned long frame3;

unsigned int aileron;
unsigned int elevator;
unsigned int throttle;
unsigned int rudder;
unsigned int ch5;
unsigned int ch6;
unsigned int ch7;
unsigned int ch8;


int ailerontrim;
int elevatortrim;
int throttletrim;
int ruddertrim;

byte keyread;
byte keyread1;
byte keyread2;

int resetcount = 0;
int modecount = 0;

boolean a_rev;
boolean e_rev;
boolean t_rev;
boolean r_rev;
boolean ch5_rev;
boolean ch6_rev;

boolean sinyal = HIGH; // Pozitif PPM pulse ile başlıyoruz istenirse reverse ediliyor
boolean LEDstatus = 0;

void setup()
{
  //  Serial.begin(9600);
  for (int n = 2; n < 10; n++)
  {
    pinMode(n, INPUT_PULLUP);
  }
  pinMode(ch5in, INPUT_PULLUP);
  pinMode(ch6in, INPUT_PULLUP);
  pinMode(PPMout, OUTPUT);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
  digitalWrite(PPMout, sinyal);
  TCCR1A = 0;
  TCCR1B = 2; // Timer 1 Clock prescaler 8
  TIMSK1 = 0;
  EEPROMread();
  a = a2 - a1;
  e = e2 - e1;
  t = t2 - t1;
  r = r2 - r1;
}

void loop()
{
  digitalWrite(LED, HIGH);
  frame1 = micros();
  aileron = analogRead(aileronin);
  aileron = analogRead(aileronin);
  aileron = analogRead(aileronin);
  aileron = map(aileron, 123, 786, 0, 1000);
  aileron = map(aileron, 0, 1000, (500 - 5 * atva), (500 + 5 * atva));
  if (a_rev == 0)
  {
    aileron = 1000 + aileron + ailerontrim;
  }
  else
  {
    aileron = 3000 - aileron - ailerontrim;
  }

  elevator = analogRead(elevatorin);
  elevator = analogRead(elevatorin);
  elevator = analogRead(elevatorin);
  elevator = map(elevator, 172, 838, 0, 1000);
  elevator = map(elevator, 0, 1000, (500 - 5 * etva), (500 + 5 * etva));
  if (e_rev == 0)
  {
    elevator = 1000 + elevator + elevatortrim;
  }
  else
  {
    elevator = 3000 - elevator - elevatortrim;
  }

  throttle = analogRead(throttlein);
  throttle = analogRead(throttlein);
  throttle = analogRead(throttlein);
  throttle = map(throttle, 0, 1023, epa1, epa2);
  if (t_rev == 0)
  {
    throttle = 1000 + throttle;
  }
  else
  {
    throttle = 3000 - throttle;
  }

  if (t_rev == 0)
  {
    throttle = map(throttle, 1000, 2000, (1000 + epa1 + throttletrim), (1000 + epa2));
  }
  else
  {
    throttle = map(throttle, 1000, 2000, (1000 + epa1), (1000 + epa2 + throttletrim));
  }

  rudder = analogRead(rudderin);
  rudder = analogRead(rudderin);
  rudder = analogRead(rudderin);
  rudder = map(rudder, 293, 481, 0, 1000);
  rudder = map(rudder, 0, 1000, (500 - 5 * rtva), (500 + 5 * rtva));
  if (r_rev == 0)
  {
    rudder = 1000 + rudder + ruddertrim;
  }
  else
  {
    rudder = 3000 - rudder - ruddertrim;
  }

  if (ch5_rev == 0)
  {
    ch5 = 1000 + 1000 * digitalRead(ch5in);
  }
  else
  {
    ch5 = 3000 - 1000 * digitalRead(ch5in);
  }

  if (ch6_rev == 0)
  {
    ch6 = 1000 + 1000 * digitalRead(ch6in);
  }
  else
  {
    ch6 = 3000 - 1000 * digitalRead(ch6in);
  }


  aileron = constrain(aileron, 800, 2200);
  elevator = constrain(elevator, 800, 2200);
  rudder = constrain(rudder, 800, 2200);
  throttle = constrain(throttle, 800, 2200);

  frame1 = micros() - frame1;
  frame2 = micros();
  PPM();
  //  printout();

  frame2 = micros() - frame2;
  frame3 = micros();

  keyread1 = PIND | B00000011;
  keyread2 = PINB | B11111100;
  keyread = keyread1 & B11111100;
  keyread = keyread | (keyread2 & B00000011);
  /* keyread1 PORT D'yi okuyor (digital 0 - 7)
     keyread2 PORT B'yi okuyor (digital 8 - 13)
     keyread2'deki iki LSBit daha sonra keyread'daki iki LSBit yerine aktarılıyor
     Böylece...
     keyread
     -------------------------------------------------
     I  7  I  6  I  5  I  4  I  3  I  2  I  1  I  0  I
     I Rud I Rud I Elv I Elv I Ail I Ail I Thr I Thr I
     I  R  I  L  I Up  I Dn  I  R  I  L  I Up  I Dn  I
     -------------------------------------------------
  */
  keys();
  frame3 = micros() - frame3;
  frame1 = frame1 + frame2 + frame3;
  if (frame1 < 22500) delayMicroseconds(22500 - frame1);
}

void PPM()
{
  cli();
  unsigned int x;
  digitalWrite(PPMout, !sinyal);
  TCNT1 = 0;
  while (TCNT1 < 600);
  TCNT1 = 0;
  digitalWrite(PPMout, sinyal);

  x = aileron * 2 - 600;
  while (TCNT1 < x);
  digitalWrite(PPMout, !sinyal);
  TCNT1 = 0;
  while (TCNT1 < 600);
  TCNT1 = 0;
  digitalWrite(PPMout, sinyal);

  x = elevator * 2 - 600;
  while (TCNT1 < x);
  digitalWrite(PPMout, !sinyal);
  TCNT1 = 0;
  while (TCNT1 < 600);
  TCNT1 = 0;
  digitalWrite(PPMout, sinyal);

  x = throttle * 2 - 600;
  while (TCNT1 < x);
  digitalWrite(PPMout, !sinyal);
  TCNT1 = 0;
  while (TCNT1 < 600);
  TCNT1 = 0;
  digitalWrite(PPMout, sinyal);

  x = rudder * 2 - 600;
  while (TCNT1 < x);
  digitalWrite(PPMout, !sinyal);
  TCNT1 = 0;
  while (TCNT1 < 600);
  TCNT1 = 0;
  digitalWrite(PPMout, sinyal);

  x = ch5 * 2 - 600;
  while (TCNT1 < x);
  digitalWrite(PPMout, !sinyal);
  TCNT1 = 0;
  while (TCNT1 < 600);
  TCNT1 = 0;
  digitalWrite(PPMout, sinyal);

  x = ch6 * 2 - 600;
  while (TCNT1 < x);
  digitalWrite(PPMout, !sinyal);
  TCNT1 = 0;
  while (TCNT1 < 600);
  TCNT1 = 0;
  digitalWrite(PPMout, sinyal);
  /*
    x = ch7 * 2 - 600;
    while (TCNT1 < x);
    digitalWrite(PPMout, LOW);
    TCNT1 = 0;
    while(TCNT1 < 600);
    TCNT1 = 0;
    digitalWrite(PPMout, HIGH);

    x = ch8 * 2 - 600;
    while (TCNT1 < x);
    digitalWrite(PPMout, LOW);
    TCNT1 = 0;
    while(TCNT1 < 600);
    digitalWrite(PPMout, HIGH);
  */
  sei();
}

void EEPROMread()
{
  /* Aileron 0, 1 MSB, LSB
     Elevator 2, 3 MSB, LSB
     Throttle 4, 5 MSB, LSB
     Rudder 6, 7 MSB, LSB
  */
  ailerontrim = (EEPROM.read(0) << :coolxf: + EEPROM.read(1);
  elevatortrim = (EEPROM.read(2) << :coolxf: + EEPROM.read(3);
  throttletrim = (EEPROM.read(4) << :coolxf: + EEPROM.read(5);
  ruddertrim = (EEPROM.read(6) << :coolxf: + EEPROM.read(7);
}

void EEPROMwrite()
{
  /* Aileron 0, 1 MSB, LSB
     Elevator 2, 3 MSB, LSB
     Throttle 4, 5 MSB, LSB
     Rudder 6, 7 MSB, LSB
  */
  int x;
  byte m;
  byte l;

  x = ailerontrim >> 8;
  m = x & 255;
  l = ailerontrim & 255;
  EEPROM.write(0, m);
  EEPROM.write(1, l);

  x = elevatortrim >> 8;
  m = x & 255;
  l = elevatortrim & 255;
  EEPROM.write(2, m);
  EEPROM.write(3, l);

  x = throttletrim >> 8;
  m = x & 255;
  l = throttletrim & 255;
  EEPROM.write(4, m);
  EEPROM.write(5, l);

  x = ruddertrim >> 8;
  m = x & 255;
  l = ruddertrim & 255;
  EEPROM.write(6, m);
  EEPROM.write(7, l);
}

void resettrims()
{
  int ledcounter;
  resetcount++;
  if (resetcount > 100) // Throttle up ve elevator down 2 saniyeden fazla basılı tutulduysa...
  {
    ailerontrim = 0;
    elevatortrim = 0;
    throttletrim = 0;
    ruddertrim = 0;
    EEPROMwrite();
    resetcount = 0;
    while (keyread < 255);
    {
      digitalWrite(LED, LEDstatus);
      keyread1 = PIND | B00000011;
      keyread2 = PINB | B11111100;
      keyread = keyread1 & B11111100;
      keyread = keyread | (keyread2 & B00000011);
      ledcounter++;
      if (ledcounter > 500)
      {
        LEDstatus = !LEDstatus;
        ledcounter = 0;
      }
    }
  }
}

void changemode()
{
  int ledcounter;
  modecount++;
  if (modecount > 100)
  {
    modecount = 0;
    sinyal = !sinyal;
    while (keyread < 255);
    {
      digitalWrite(LED, LEDstatus);
      keyread1 = PIND | B00000011;
      keyread2 = PINB | B11111100;
      keyread = keyread1 & B11111100;
      keyread = keyread | (keyread2 & B00000011);
      ledcounter++;
      if (ledcounter > 500)
      {
        LEDstatus = !LEDstatus;
        ledcounter = 0;
      }
    }
  }
}

void keys()
{
  if (keyread < 255)
  {
    /* 2 saniye boyunca Elevator down ve throttle up trimi
       basılı tutulursa trimler resetleniyor
       Bu süreyi resetcount değişkeni tutuyor ve resettrims()
       altprogramında güncellenip 100'ü geçince
       reset işlemi uygulanıyor
    */
    if (keyread == B11101101)
    {
      resettrims();
      return;
    }
    if (keyread == B11011110)
    {
      changemode();
      return;
    }
    resetcount = 0;
    if ((keyread & B00000001) == 0)
    {
      if (t_rev == 0)
      {
        throttletrim--;
      }
      else
      {
        throttletrim++;
      }
    }

    if ((keyread & B00000010) == 0)
    {
      if (t_rev == 0)
      {
        throttletrim++;
      }
      else
      {
        throttletrim--;
      }
    }

    if ((keyread & B00000100) == 0)
    {
      if (a_rev == 0)
      {
        ailerontrim--;
      }
      else
      {
        ailerontrim++;
      }
    }

    if ((keyread & B00001000) == 0)
    {
      if (a_rev == 0)
      {
        ailerontrim++;
      }
      else
      {
        ailerontrim--;
      }
    }

    if ((keyread & B00010000) == 0)
    {
      if (e_rev == 0)
      {
        elevatortrim--;
      }
      else
      {
        elevatortrim++;
      }
    }

    if ((keyread & B00100000) == 0)
    {
      if (e_rev == 0)
      {
        elevatortrim++;
      }
      else
      {
        elevatortrim--;
      }
    }

    if ((keyread & B01000000) == 0)
    {
      if (r_rev == 0)
      {
        ruddertrim--;
      }
      else
      {
        ruddertrim++;
      }
    }

    if ((keyread & B10000000) == 0)
    {
      if (r_rev == 0)
      {
        ruddertrim++;
      }
      else
      {
        ruddertrim--;
      }
    }

    if (throttletrim < -300) throttletrim = -300;
    if (throttletrim > 300) throttletrim = 300;
    if (ailerontrim < -300) ailerontrim = -300;
    if (ailerontrim > 300) ailerontrim = 300;
    if (elevatortrim < -300) elevatortrim = -300;
    if (elevatortrim > 300) elevatortrim = 300;
    if (ruddertrim < -300) ruddertrim = -300;
    if (ruddertrim > 300) ruddertrim = 300;

    EEPROMwrite();
  }
}

void printout()
{
  Serial.print(aileron);
  Serial.print("  ");
  Serial.print(ailerontrim);
  Serial.print("  ");
  Serial.print(elevator);
  Serial.print("  ");
  Serial.print(elevatortrim);
  Serial.print("  ");
  Serial.print(throttle);
  Serial.print("  ");
  Serial.print(throttletrim);
  Serial.print("  ");
  Serial.print(rudder);
  Serial.print("  ");
  Serial.println(ruddertrim);
}

Bu versiyonda şu numaralar var:
Bir LED eklendi sisteme. Normal çalışma sırasında sürekli yanacak. İki farklı reset işlemi var. Bunlardan birisi trim reset. Elevatör Down ile Throttle Up trimlerini birlikte basılı tutup 3 saniye bekliyoruz. Tüm trimler sıfırlanıp EEPROM'a yazılıyor. LED yanıp sönmeye başlıyor. Butonları bırakana kadar bekliyor.
İkinci işlev tam bir reset değil. Ne kadar gerekli onu da bilmiyorum ama bulunsun. Çıkış darbelerini HIGH ya da LOW yapmak yani ters çevirmek için. Bunun için bu sefer ters yani elevatör up throttle down trimlere birlikte basıp 3 saniye bekliyoruz. Çıkış darbesi tersine dönüyor ve LED yanıp sönmeye başlıyor. Yine butonları bırakana kadar beklemede kalıyoruz.
Programı compile etmeden önce her bir kanalı reverse edebiliyoruz. Travel adjust değişkenlerini yüzde olarak ayarlıyoruz. Throttle endpointlerini giriyoruz. Bu halde compile edip Arduino'ya yüklediğimizde modelin tüm ayarları yapılmış oluyor.

Bundan sonra ne yapılabilir?
Dört kanalın trim değerleri var. Tümü integer yani ikişer byte. Etti 8 byte.
Üç kanalın travel adjust ayarları var. Üç tane integer yani 6 byte.
Throttle kanalının üst ve alt uç limitleri var. Etti 4 byte.
Altı kanalın reverse değerleri var. Her biri bir bitten toplam 1 byte.
Yani bir model için toplam 19 byte gerekiyor.
Yuvarlak hesap 20 desek...
1024 byte EEPROM'a bunlardan 50 tane sığar. Yani tamı tamına elli model hafızamız var.
Demek ki bundan sonraki aşamada sisteme bir (muhtemelen LCD) gösterge ekleme planı yapmamız gerekecek.
Bazı buton kombinasyonları ile açılışta aleti programlama moduna alıp model seçerek ilgili modelin datasını anlık olarak hafızaya yükleyip kullanabiliriz.
Yani...
Çok çalışmam gerek! :D
 
Gerçek lövye ile model uçurmak

LCD ekran ve model hafızası gercekten projeyi 1 tık yukarı taşıyacaktır. Kolay gelsin abi :D


Sent from my iPhone using Tapatalk
 
Gerçek lövye ile model uçurmak

Bu kadar hatayı bir arada nasıl yapabildiğime şaşıyorum ama bu son hata için herhangi bir dokümana rastlamadım bugüne kadar.
Bu akşam bir alıcıya dört servo bağladım ve trainer porttan (doğru jack kullanarak) giriş yaptım. Servolar abuk sabuk hareketler yapıyorlar, kontrollere kademeli yanıt veriyorlardı. Canım sıkıldı. Birkaç gündür sürekli testler yaparken kanal değerlerini hep kontrol etmiştim. Tümü doğru değerler okuyorlardı. Hatta hassas ayarlarla stickler tam ortadayken kanallar 1500 mikrosaniye okuyor hale gelmişlerdi. Ama gerçek hayatta çıkan PPM sinyalinin saçmaladığı da çok açıktı. Sonra...

Daha önce hassas servo kontrolünü 8 bit sayıcı ile yapma çabalarımı belki hatırlarsınız. Orada yaptığım bir hata geldi aklıma. Interruptlar!!!

Hassas zamanlama için ben interruptları kapatıyordum. Daha sonra interruptlar kapalıyken servonun düzgün değil kademeli hareket ettiğini farketmiştim ve interruptlarla elleşmeyince sorun çözülmüştü. Bu uygulamada da PPM çıkışı aşamasında interruptları kapatıyordum ki zamanlama kaymasın. Ama sanırım timer okumaları konusunda interruptlar kullanılıyor sistemde. Kısaca interrupt kapatma ve daha sonra açma satırlarını silince servolar tereyağında yok en kalite makine yağında hareket eder gibi çalışmaya başladılar. :D :D :D

Yanıtlayamadığım soru ise bu durumu simülatörde neden farkedemediğim. Muhtemelen sistemin çözünürlüğü normalde kullandığım gibi 1024 değil çok daha düşük ve ekranda kontrol yüzeyi titremelerini de net göremeyebiliyor insan.

Bu arada bir sorun da bu haliyle trim tepkisinin aşırı hızlı oluşu idi. Onu engellemek için sisteme bir "frame counter" ekledim ve her dört PPM frame'de bir butonlar değerlendiriliyor. Bu şekilde çok daha gerçekçi bir trim tepkisi elde etmiş oldum.
 
Gerçek lövye ile model uçurmak

Valla ben olsam buna hata demezdim ama. Netice de yeni bir platformda farklı bir tepki karşılaşmış ve her zaman oldugu gibi yine şahane bir sekilde çözümlemissin :halay:


Sent from my iPhone using Tapatalk
 
Gerçek lövye ile model uçurmak

Sümer Yamaner' Alıntı:
Bu kadar hatayı bir arada nasıl yapabildiğime şaşıyorum ama bu son hata için herhangi bir dokümana rastlamadım bugüne kadar.
Bu akşam bir alıcıya dört servo bağladım ve trainer porttan (doğru jack kullanarak) giriş yaptım. Servolar abuk sabuk hareketler yapıyorlar, kontrollere kademeli yanıt veriyorlardı. Canım sıkıldı. Birkaç gündür sürekli testler yaparken kanal değerlerini hep kontrol etmiştim. Tümü doğru değerler okuyorlardı. Hatta hassas ayarlarla stickler tam ortadayken kanallar 1500 mikrosaniye okuyor hale gelmişlerdi. Ama gerçek hayatta çıkan PPM sinyalinin saçmaladığı da çok açıktı. Sonra...

Daha önce hassas servo kontrolünü 8 bit sayıcı ile yapma çabalarımı belki hatırlarsınız. Orada yaptığım bir hata geldi aklıma. Interruptlar!!!

Hassas zamanlama için ben interruptları kapatıyordum. Daha sonra interruptlar kapalıyken servonun düzgün değil kademeli hareket ettiğini farketmiştim ve interruptlarla elleşmeyince sorun çözülmüştü. Bu uygulamada da PPM çıkışı aşamasında interruptları kapatıyordum ki zamanlama kaymasın. Ama sanırım timer okumaları konusunda interruptlar kullanılıyor sistemde. Kısaca interrupt kapatma ve daha sonra açma satırlarını silince servolar tereyağında yok en kalite makine yağında hareket eder gibi çalışmaya başladılar. :D :D :D

Yanıtlayamadığım soru ise bu durumu simülatörde neden farkedemediğim. Muhtemelen sistemin çözünürlüğü normalde kullandığım gibi 1024 değil çok daha düşük ve ekranda kontrol yüzeyi titremelerini de net göremeyebiliyor insan.

Bu arada bir sorun da bu haliyle trim tepkisinin aşırı hızlı oluşu idi. Onu engellemek için sisteme bir "frame counter" ekledim ve her dört PPM frame'de bir butonlar değerlendiriliyor. Bu şekilde çok daha gerçekçi bir trim tepkisi elde etmiş oldum.

abi doktor değilsin ama hastan çok emin ol :D
 
Gerçek lövye ile model uçurmak

Onur , alıştıra alıştıra söyleyelim dedik , Sümer Abi , gerçek bir profesör doktordur üstelik...... :laugh:...... :lol:
 
Gerçek lövye ile model uçurmak

Hakan Ülgenalp' Alıntı:
Onur , alıştıra alıştıra söyleyelim dedik , Sümer Abi , gerçek bir profesör doktordur üstelik...... :laugh:...... :lol:
Aynı zamanda pilot olduğunu söylemeyin sakın çok moral bozucu oluyor. :lol: :lol: :lol: