Servo senkronizasyon modülü

Servo senkronizasyon modülü

Bu konuyu 6 Mart günü açmışım. Bugün 19 Mart ve planlanan modülün "Pro" ve "Lite" versiyonları kullanıma hazır. Tüm testler ve debug işlemlerinden geçtiler.
Arşivde bulunması açısından kodları buraya koyuyorum. Bana göre gerçekten de ilginç programlama teknikleri içeriyorlar.

Önce "Pro" versiyonu. Üç servoya kadar hem merkez hem de iki uç ayrı ayrı ayarlanabiliyor. Çok gerekli mi bilemiyorum ama Futaba'nın modülü de böyle.

Kod:
#include <EEPROM.h>
const byte servoin = 3;
const byte servo1 = 6;
const byte servo2 = 5;
const byte servo3 = 4;
const byte mode1 = 14;
const byte mode2 = 15;
const byte decrease = 16;
const byte increase = 17;
const byte centerLED = 12;
const byte epa1LED = 11;
const byte epa2LED = 10;
const byte servo1LED = 9;
const byte servo2LED = 8;
const byte servo3LED = 7;

volatile int servoinPWM = 1500;
volatile int servo1PWM = 1500;
volatile int servo2PWM = 1500;
volatile int servo3PWM = 1500;
volatile int intcounter = 0;
volatile byte sregvalue; // ISR sırasında status registerini saklıyor

long x;
volatile byte progflag = 0;
volatile byte keyflag = 0;
byte eepromerror = 0;

byte hibyte;
byte lobyte;
unsigned long timer;
unsigned long fark;

// CNT değerleri - 700 ile + 700 arası, EPA değerleri 0 - 700 arası
int servo1cnt;
unsigned int servo1epa1;
unsigned int servo1epa2;
int servo2cnt;
unsigned int servo2epa1;
unsigned int servo2epa2;
int servo3cnt;
unsigned int servo3epa1;
unsigned int servo3epa2;

volatile byte LED = 0;

byte keypress = B00111111;
int key = 0;
int key1 = 0;
int key2 = 0;
int b = 0;
const int debounce = 200;
const int bounce = 160;


void timerinit()
{
  noInterrupts();  // disable global interrupts
  TCCR2A = 0; // prescaler 256
  TCCR2B = 0;
  TCCR2B |= (0 << CS20);
  TCCR2B |= (1 << CS21);
  TCCR2B |= (1 << CS22);
  TCNT2 = 0;
  TIMSK2 |= (1 << TOIE2); // enable global interrupts
  interrupts();
}


ISR(TIMER2_OVF_vect)
{
  sregvalue = SREG;
  intcounter++;
  if (intcounter > 4)
  {
    intcounter = 0;
    if (progflag == 0)
    {
      x = servoinPWM - 1500; // x -700 ile + 700 arasında bir değer alıyor
      if (x < 0)
      {
        servo1PWM = 1500 + ((x * servo1epa1) / 700) + servo1cnt; //Servo1 için çıkış değeri oluşturuluyor
        servo2PWM = 1500 + ((x * servo2epa1) / 700) + servo2cnt; //Servo2 için çıkış değeri oluşturuluyor
        servo3PWM = 1500 + ((x * servo3epa1) / 700) + servo3cnt; //Servo3 için çıkış değeri oluşturuluyor
      }
      else
      {
        servo1PWM = ((x * servo1epa2) / 700) + 1500 + servo1cnt; //Servo1 için çıkış değeri oluşturuluyor
        servo2PWM = ((x * servo2epa2) / 700) + 1500 + servo2cnt; //Servo2 için çıkış değeri oluşturuluyor
        servo3PWM = ((x * servo3epa2) / 700) + 1500 + servo3cnt; //Servo3 için çıkış değeri oluşturuluyor
      }
    }
    if (servoinPWM > 800)
    {
      digitalWrite(servo1, HIGH);
      delayMicroseconds(servo1PWM);
      digitalWrite(servo1, LOW);

      digitalWrite(servo2, HIGH);
      delayMicroseconds(servo2PWM);
      digitalWrite(servo2, LOW);

      digitalWrite(servo3, HIGH);
      delayMicroseconds(servo3PWM);
      digitalWrite(servo3, LOW);
    }
  }
  SREG = sregvalue;
}


void setup()
{
  pinMode(mode1, INPUT_PULLUP);
  pinMode(mode2, INPUT_PULLUP);
  pinMode(decrease, INPUT_PULLUP);
  pinMode(increase, INPUT_PULLUP);
  pinMode(centerLED, OUTPUT);
  pinMode(epa1LED, OUTPUT);
  pinMode(epa2LED, OUTPUT);
  pinMode(servo1LED, OUTPUT);
  pinMode(servo2LED, OUTPUT);
  pinMode(servo3LED, OUTPUT);
  pinMode(servo1, OUTPUT);
  pinMode(servo2, OUTPUT);
  pinMode(servo3, OUTPUT);

  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);

  if ((digitalRead(mode1) == 0) && (digitalRead(mode2) == 0))
  {
    keyflag = 1;
  }
  delay(1000);
  if ((digitalRead(mode1) == 0) && (digitalRead(mode2) == 0) && keyflag == 1)
  {
    progflag = 1;
    flashleds2(); //Programlama moduna girildiğini göstermek için tüm LED'ler birlikte beş kez hızlıca yakılıp söndürülüyor.
  }
  else
  {
    flashleds(); //Normal modu göstermek için tüm LED'ler sıra ile bir kez yakılıp söndürülüyor
  }

  EEPROMtest();

  if (eepromerror > 0) // EEPROM hatasında servo LED'lerini yakıp söndürerek beklemede kalıyoruz. Programa girmiyoruz. Güç kesilene kadar böyle devam.
  {
    while (eepromerror > 0)
    {
      digitalWrite(servo1, HIGH);
      digitalWrite(servo2, HIGH);
      digitalWrite(servo3, HIGH);
      delay(300);
      digitalWrite(servo1, LOW);
      digitalWrite(servo2, LOW);
      digitalWrite(servo3, LOW);
      delay(300);
    }
  }

  EEPROMoku();
  delay(100);
  timerinit();
}

void loop()
{
  if (progflag == 0)
  {
    normal();
  }
  else
  {
    progmode();
  }
}

void normal() // Programlama modunda değilsek loop()'tan sürekli bu işlev çağrılıyor
{
  digitalWrite(servo1LED, LED);
  if (LED == 0)
  {
    LED = 1;
  }
  else
  {
    LED = 0;
  }
  noInterrupts();
  servoinPWM = pulseIn(servoin, HIGH, 21000); //Alıcıdan sinyali mikrosaniye olarak okuyoruz
  x = servoinPWM;
  interrupts();
}

void progmode() // Programlama modunda isek loop()'tan sürekli bu çağrılıyor
{
  int servosira = 1; // 1 No'lu servo ile başlıyoruz
  int islevsira = 1; // Center modu ile başlıyoruz. 1: Center, 2: Alt EPA, 3: Üst EPA
  int pressedkey = 0; // 0: Key yok, 1: Mode1(servo), 2: Mode2(işlev), 3: Decrease, 4: Increase, 5: Exit

  while (pressedkey < 5)
  {
    noInterrupts();
    switch (islevsira)
    {
      case 1:
        servo1PWM = 1500 + servo1cnt;
        servo2PWM = 1500 + servo2cnt;
        servo3PWM = 1500 + servo3cnt;
        break;
      case 2:
        servo1PWM = 1500 + servo1cnt - servo1epa1;
        servo2PWM = 1500 + servo2cnt - servo2epa1;
        servo3PWM = 1500 + servo3cnt - servo3epa1;

        break;
      case 3:
        servo1PWM = 1500 + servo1cnt + servo1epa2;
        servo2PWM = 1500 + servo2cnt + servo2epa2;
        servo3PWM = 1500 + servo3cnt + servo3epa2;
        break;
    }
    servoinPWM = 1500;
    interrupts();
    pressedkey = button();
    switch (pressedkey)
    {
      case 0:
        break;
      case 1:
        servosira++;
        if (servosira > 3) servosira = 1;
        break;
      case 2:
        islevsira++;
        if (islevsira > 3) islevsira = 1;
        break;
      case 3: // Burada o an seçili olan parametreyi bir azaltacağız. Range check yapıp düzelteceğiz.
        if (servosira == 1)
        {
          switch (islevsira)
          {
            case 1:
              servo1cnt = servo1cnt - 4;
              if (servo1cnt < (-200)) servo1cnt = -200;
              break;
            case 2:
              servo1epa1 = servo1epa1 - 4;
              if (servo1epa1 < 1) servo1epa1 = 1;
              break;
            case 3:
              servo1epa2 = servo1epa2 - 4;
              if (servo1epa2 < 1) servo1epa2 = 1;
              break;
          }
        }
        if (servosira == 2)
        {
          switch (islevsira)
          {
            case 1:
              servo2cnt = servo2cnt - 4;
              if (servo2cnt < (-200)) servo2cnt = -200;
              break;
            case 2:
              servo2epa1 = servo2epa1 - 4;
              if (servo2epa1 < 1) servo2epa1 = 1;
              break;
            case 3:
              servo2epa2 = servo2epa2 - 4;
              if (servo2epa2 < 1) servo2epa2 = 1;
              break;
          }

        }
        if (servosira == 3)
        {
          switch (islevsira)
          {
            case 1:
              servo3cnt = servo3cnt - 4;
              if (servo3cnt < (-200)) servo3cnt = -200;
              break;
            case 2:
              servo3epa1 = servo3epa1 - 4;
              if (servo3epa1 < 1) servo3epa1 = 1;
              break;
            case 3:
              servo3epa2 = servo3epa2 - 4;
              if (servo3epa2 < 1) servo3epa2 = 1;
              break;
          }
        }
        break;
      case 4: // Burada o an seçili olan parametreyi bir artıracağız. Range check yapıp düzelteceğiz.
        if (servosira == 1)
        {
          switch (islevsira)
          {
            case 1:
              servo1cnt = servo1cnt + 4;
              if (servo1cnt > 200) servo1cnt = 200;
              break;
            case 2:
              servo1epa1 = servo1epa1 + 4;
              if (servo1epa1 > 700) servo1epa1 = 700;
              break;
            case 3:
              servo1epa2 = servo1epa2 + 4;
              if (servo1epa2 > 700) servo1epa2 = 700;
              break;
          }
        }
        if (servosira == 2)
        {
          switch (islevsira)
          {
            case 1:
              servo2cnt = servo2cnt + 4;
              if (servo2cnt > 200) servo2cnt = 200;
              break;
            case 2:
              servo2epa1 = servo2epa1 + 4;
              if (servo2epa1 > 700) servo2epa1 = 700;
              break;
            case 3:
              servo2epa2 = servo2epa2 + 4;
              if (servo2epa2 > 700) servo2epa2 = 700;
              break;
          }

        }
        if (servosira == 3)
        {
          switch (islevsira)
          {
            case 1:
              servo3cnt = servo3cnt + 4;
              if (servo3cnt > 200) servo3cnt = 200;
              break;
            case 2:
              servo3epa1 = servo3epa1 + 4;
              if (servo3epa1 > 700) servo3epa1 = 700;
              break;
            case 3:
              servo3epa2 = servo3epa2 + 4;
              if (servo3epa2 > 700) servo3epa2 = 700;
              break;
          }
        }
        break;
    }


    if (pressedkey > 0);
    {
      digitalWrite(centerLED, LOW);
      digitalWrite(epa1LED, LOW);
      digitalWrite(epa2LED, LOW);
      digitalWrite(servo1LED, LOW);
      digitalWrite(servo2LED, LOW);
      digitalWrite(servo3LED, LOW);

      switch (servosira)
      {
        case 1:
          digitalWrite(servo1LED, HIGH);
          break;
        case 2:
          digitalWrite(servo2LED, HIGH);
          break;
        case 3:
          digitalWrite(servo3LED, HIGH);
          break;
      }

      switch (islevsira)
      {
        case 1:
          digitalWrite(centerLED, HIGH);
          break;
        case 2:
          digitalWrite(epa1LED, HIGH);
          break;
        case 3:
          digitalWrite(epa2LED, HIGH);
          break;
      }
    }

  }
  EEPROMyaz();
  while (1 == 1) // Burada artık programı kilitliyoruz. Servo LED'leri hızlı yanıp sönüyorlar. Artık programlama bitti. Sistemin resetlenmesi gerekiyor.
  {
    digitalWrite(servo1LED, HIGH);
    digitalWrite(servo2LED, HIGH);
    digitalWrite(servo3LED, HIGH);
    delay(100);
    digitalWrite(servo1LED, LOW);
    digitalWrite(servo2LED, LOW);
    digitalWrite(servo3LED, LOW);
    delay(100);
  }
}



void EEPROMoku()
{
  noInterrupts();
  servo1cnt = EEPROM.read(1) + 256 * EEPROM.read(0) - 2000;
  servo1epa1 = EEPROM.read(3) + 256 * EEPROM.read(2);
  servo1epa2 = EEPROM.read(5) + 256 * EEPROM.read(4);
  servo2cnt = EEPROM.read(7) + 256 * EEPROM.read(6) - 2000;
  servo2epa1 = EEPROM.read(9) + 256 * EEPROM.read(:coolxf:;
  servo2epa2 = EEPROM.read(11) + 256 * EEPROM.read(10);
  servo3cnt = EEPROM.read(13) + 256 * EEPROM.read(12) - 2000;
  servo3epa1 = EEPROM.read(15) + 256 * EEPROM.read(14);
  servo3epa2 = EEPROM.read(17) + 256 * EEPROM.read(16);
  interrupts();
}


void EEPROMyaz()
{
  noInterrupts();
  hibyte = (servo1cnt + 2000) / 256;
  lobyte = (servo1cnt + 2000) - 256 * hibyte;
  EEPROM.write(0, hibyte);
  EEPROM.write(1, lobyte);

  hibyte = servo1epa1 / 256;
  lobyte = servo1epa1 - 256 * hibyte;
  EEPROM.write(2, hibyte);
  EEPROM.write(3, lobyte);

  hibyte = servo1epa2 / 256;
  lobyte = servo1epa2 - 256 * hibyte;
  EEPROM.write(4, hibyte);
  EEPROM.write(5, lobyte);

  hibyte = (servo2cnt + 2000) / 256;
  lobyte = (servo2cnt + 2000) - 256 * hibyte;
  EEPROM.write(6, hibyte);
  EEPROM.write(7, lobyte);

  hibyte = servo2epa1 / 256;
  lobyte = servo2epa1 - 256 * hibyte;
  EEPROM.write(8, hibyte);
  EEPROM.write(9, lobyte);

  hibyte = servo2epa2 / 256;
  lobyte = servo2epa2 - 256 * hibyte;
  EEPROM.write(10, hibyte);
  EEPROM.write(11, lobyte);

  hibyte = (servo3cnt + 2000) / 256;
  lobyte = (servo3cnt + 2000) - 256 * hibyte;
  EEPROM.write(12, hibyte);
  EEPROM.write(13, lobyte);

  hibyte = servo3epa1 / 256;
  lobyte = servo3epa1 - 256 * hibyte;
  EEPROM.write(14, hibyte);
  EEPROM.write(15, lobyte);

  hibyte = servo3epa2 / 256;
  lobyte = servo3epa2 - 256 * hibyte;
  EEPROM.write(16, hibyte);
  EEPROM.write(17, lobyte);
  interrupts();
}


void EEPROMtest() // EEPROM testi yapılıp flag ile sonuç bildiriliyor
{
  eepromerror = 0;
  unsigned long b = 0;
  unsigned int temp;
  for (int i = 0; i < 18; i++)
  {
    b = b + EEPROM.read(i);
  }
  if (b == 4590)
  {
    temp = EEPROM.read(0);
    EEPROM.write(0, 0);
    if (EEPROM.read(0) != 0)
    {
      eepromerror = 1;
    }
    EEPROM.write(0, temp);
  }
}





int button() // 0: Geçerli tuş yok. 1: Mode1. 2: Mode2. 3: Decrease. 4: Increase. 5: Done.
{
  key1 = buttonbas();
  key2 = debouncebutton();
  if ((key1 == key2) && ((key1 * key2) != 0))
  {
    return key1;
  }
  return 0;
}

int buttonbas()
{
  keypress = PINC & B00001111;
  for (int n = 0; n < 10; n++)
  {
    keypress &= PINC;
  }
  if (keypress == B00001100) return 5;
  if (keypress == B00001110) return 1;
  if (keypress == B00001101) return 2;
  if (keypress == B00001011) return 3;
  if (keypress == B00000111) return 4;
  return 0;
}

int debouncebutton() //Buraya gelirken key1 değişkeni basıldığı belirlenen butonu içeriyor. Yani 0 - 5 arası bir değer.
{
  if (key1 == 0) return key1; //Tuşa basılmamış ise hiçbir şey yapmadan geri dön
  b = 0; //Sayaç sıfırlanıyor
  for (int n = 0; n < debounce; n++)
  {
    key = buttonbas(); //Butonlar "debounce" kez okunuyor
    if (key == key1) b++; //Eğer okunan değer ilk okunan değer ile aynı ise b sayacı bir artırılıyor
    else if (key != 0) return 0; //Farklı bir değer okunduysa ve bu değer 0 değil ise bu durum bounce nedeniyle değil başka butona basma nedeniyle olmuştur. 0 döndürüyoruz.
  }
  if (b < bounce) return 0; //Okunan değerlerin en az % 80'i key1 ile aynı olmalı. Yoksa 0 döndürüyoruz
  while (buttonbas() != 0) //Buraya geldiğimize göre "debounce" test okumasındaki değerlerin en az "bounce"'ı orijinal key1 değeri ile aynı demektir. Artık butonun bırakılmasını bekliyor ve key1 değerini döndürüyoruz
  {
  }
  return key1;
}


void flashleds()
{
  digitalWrite(centerLED, HIGH);
  delay(200);
  digitalWrite(centerLED, LOW);

  digitalWrite(epa1LED, HIGH);
  delay(200);
  digitalWrite(epa1LED, LOW);

  digitalWrite(epa2LED, HIGH);
  delay(200);
  digitalWrite(epa2LED, LOW);

  digitalWrite(servo1LED, HIGH);
  delay(200);
  digitalWrite(servo1LED, LOW);

  digitalWrite(servo2LED, HIGH);
  delay(200);
  digitalWrite(servo2LED, LOW);

  digitalWrite(servo3LED, HIGH);
  delay(200);
  digitalWrite(servo3LED, LOW);
}

void flashleds2() //Tüm LED'leri birlikte beş kez hızlıca yakıp söndüren işlev
{
  for (int n = 0; n < 5; n++)
  {
    digitalWrite(centerLED, HIGH);
    digitalWrite(epa1LED, HIGH);
    digitalWrite(epa2LED, HIGH);
    digitalWrite(servo1LED, HIGH);
    digitalWrite(servo2LED, HIGH);
    digitalWrite(servo3LED, HIGH);
    delay(200);
    digitalWrite(centerLED, LOW);
    digitalWrite(epa1LED, LOW);
    digitalWrite(epa2LED, LOW);
    digitalWrite(servo1LED, LOW);
    digitalWrite(servo2LED, LOW);
    digitalWrite(servo3LED, LOW);
    delay(200);
  }
}
 
Bu da "Lite" versiyonu. Bunda sadece merkezler eşitleniyor. Uç noktalarda uzun süreler kalmayacağı düşünülerek daha basit olan bu modül tercih edilebilir. Doğal olarak bu daha "ucuz" olacak! :p :D :p

Kod:
#include <EEPROM.h>


const byte servoin = 3;
const byte servo1 = 6;
const byte servo2 = 5;
const byte servo3 = 4;
const byte mode1 = 14;
const byte mode2 = 15;
const byte select = 16;
const byte servo1LED = 9;
const byte servo2LED = 8;
const byte servo3LED = 7;

volatile int servoinPWM = 1500;
volatile int servo1PWM = 1500;
volatile int servo2PWM = 1500;
volatile int servo3PWM = 1500;
volatile int intcounter = 0;
volatile byte sregvalue; // ISR sırasında status registerini saklıyor
int x;

int keyflag = 0;
int progflag = 0;

byte eepromerror = 0;

byte hibyte;
byte lobyte;
unsigned long timer;

// CNT değerleri - 700 ile + 700 arası, EPA değerleri 0 - 700 arası
int servo1cnt;
int servo2cnt;
int servo3cnt;

volatile byte LED = 0;

byte keypress = B00000111;
int key = 0;
int key1 = 0;
int key2 = 0;
int b = 0;
const int debounce = 200;
const int bounce = 160;


void timerinit()
{
  noInterrupts();  // disable global interrupts
  TCCR2A = 0; // prescaler 256
  TCCR2B = 0;
  TCCR2B |= (0 << CS20);
  TCCR2B |= (1 << CS21);
  TCCR2B |= (1 << CS22);
  TCNT2 = 0;
  TIMSK2 |= (1 << TOIE2); // enable global interrupts
  interrupts();
}


ISR(TIMER2_OVF_vect)
{
  sregvalue = SREG;
  intcounter++;
  if (intcounter > 4)
  {
    intcounter = 0;
    if (servoinPWM > 800)
    {
        servo1PWM = servoinPWM + servo1cnt;
        servo2PWM = servoinPWM + servo2cnt;
        servo3PWM = servoinPWM + servo3cnt;
        digitalWrite(servo1, HIGH);
        delayMicroseconds(servo1PWM);
        digitalWrite(servo1, LOW);

        digitalWrite(servo2, HIGH);
        delayMicroseconds(servo2PWM);
        digitalWrite(servo2, LOW);

        digitalWrite(servo3, HIGH);
        delayMicroseconds(servo3PWM);
        digitalWrite(servo3, LOW);
    }
  }
  SREG = sregvalue;
}


void setup()
{
  pinMode(mode1, INPUT_PULLUP);
  pinMode(mode2, INPUT_PULLUP);
  pinMode(select, INPUT_PULLUP);
  pinMode(servo1LED, OUTPUT);
  pinMode(servo2LED, OUTPUT);
  pinMode(servo3LED, OUTPUT);
  pinMode(servo1, OUTPUT);
  pinMode(servo2, OUTPUT);
  pinMode(servo3, OUTPUT);

  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);

  if ((digitalRead(mode1) == 0) && (digitalRead(mode2) == 0))
  {
    keyflag = 1;
  }
  delay(1000);
  if ((digitalRead(mode1) == 0) && (digitalRead(mode2) == 0) && keyflag == 1)
  {
    progflag = 1;
    flashleds2(); //Programlama moduna girildiğini göstermek için tüm LED'ler birlikte beş kez hızlıca yakılıp söndürülüyor.
  }
  else
  {
    flashleds(); //Normal modu göstermek için tüm LED'ler sıra ile bir kez yakılıp söndürülüyor
  }

  EEPROMtest();

  if (eepromerror > 0) // EEPROM hatasında servo LED'lerini yakıp söndürerek beklemede kalıyoruz. Programa girmiyoruz. Güç kesilene kadar böyle devam.
  {
    while (eepromerror > 0)
    {
      digitalWrite(servo1, HIGH);
      digitalWrite(servo2, HIGH);
      digitalWrite(servo3, HIGH);
      delay(300);
      digitalWrite(servo1, LOW);
      digitalWrite(servo2, LOW);
      digitalWrite(servo3, LOW);
      delay(300);
    }
  }

  EEPROMoku();
  delay(100);
  timerinit();
}

void loop()
{
  if (progflag == 0)
  {
    normal();
  }
  else
  {
    progmode();
  }
}

void normal() // Programlama modunda değilsek loop()'tan sürekli bu işlev çağrılıyor
{
  digitalWrite(servo1LED, LED);
  if (LED == 0)
  {
    LED = 1;
  }
  else
  {
    LED = 0;
  }
  noInterrupts();
  servoinPWM = pulseIn(servoin, HIGH, 21000); //Alıcıdan sinyali mikrosaniye olarak okuyoruz
  interrupts();
}

void progmode() // Programlama modunda isek loop()'tan sürekli bu çağrılıyor
{
  int servosira = 1; // 1 No'lu servo ile başlıyoruz
  int pressedkey = 0; // 0: Key yok, 1: Decrease, 2: Increase, 3: Select, 4: Exit

  while (pressedkey < 4)
  {
    servo1PWM = 1500 + servo1cnt;
    servo2PWM = 1500 + servo2cnt;
    servo3PWM = 1500 + servo3cnt;

    pressedkey = button();
    switch (pressedkey)
    {
      case 0:
        break;
      case 1:
        switch (servosira)
        {
          case 1:
            servo1cnt = servo1cnt - 4;
            if (servo1cnt < (-700)) servo1cnt = -700;
            break;
          case 2:
            servo2cnt = servo2cnt - 4;
            if (servo2cnt < (-700)) servo2cnt = -700;
            break;
          case 3:
            servo3cnt = servo3cnt - 4;
            if (servo3cnt < (-700)) servo3cnt = -700;
            break;
        }
        break;
      case 2:
        switch (servosira)
        {
          case 1:
            servo1cnt = servo1cnt + 4;
            if (servo1cnt > 700) servo1cnt = 700;
            break;
          case 2:
            servo2cnt = servo2cnt + 4;
            if (servo2cnt > 700) servo2cnt = 700;
            break;
          case 3:
            servo3cnt = servo3cnt + 4;
            if (servo3cnt > 700) servo3cnt = 700;
            break;
        }
        break;
      case 3:
        servosira++;
        if (servosira > 3) servosira = 1;
        break;
    }
    if (pressedkey > 0);
    {
      digitalWrite(servo1LED, LOW);
      digitalWrite(servo2LED, LOW);
      digitalWrite(servo3LED, LOW);
      switch (servosira)
      {
        case 1:
          digitalWrite(servo1LED, HIGH);
          break;
        case 2:
          digitalWrite(servo2LED, HIGH);
          break;
        case 3:
          digitalWrite(servo3LED, HIGH);
          break;
      }
    }
  }
  EEPROMyaz();
  while (1 == 1) // Burada artık programı kilitliyoruz. Servo LED'leri hızlı yanıp sönüyorlar. Artık programlama bitti. Sistemin resetlenmesi gerekiyor.
  {
    digitalWrite(servo1LED, HIGH);
    digitalWrite(servo2LED, HIGH);
    digitalWrite(servo3LED, HIGH);
    delay(100);
    digitalWrite(servo1LED, LOW);
    digitalWrite(servo2LED, LOW);
    digitalWrite(servo3LED, LOW);
    delay(100);
  }
}

void EEPROMoku()
{
  noInterrupts();
  servo1cnt = EEPROM.read(1) + 256 * EEPROM.read(0) - 2000;
  servo2cnt = EEPROM.read(7) + 256 * EEPROM.read(6) - 2000;
  servo3cnt = EEPROM.read(13) + 256 * EEPROM.read(12) - 2000;
  interrupts();
}

void EEPROMyaz()
{
  noInterrupts();
  hibyte = (servo1cnt + 2000) / 256;
  lobyte = (servo1cnt + 2000) - 256 * hibyte;
  EEPROM.write(0, hibyte);
  EEPROM.write(1, lobyte);
  hibyte = (servo2cnt + 2000) / 256;
  lobyte = (servo2cnt + 2000) - 256 * hibyte;
  EEPROM.write(6, hibyte);
  EEPROM.write(7, lobyte);
  hibyte = (servo3cnt + 2000) / 256;
  lobyte = (servo3cnt + 2000) - 256 * hibyte;
  EEPROM.write(12, hibyte);
  EEPROM.write(13, lobyte);
  interrupts();
}


void EEPROMtest() // EEPROM testi yapılıp flag ile sonuç bildiriliyor
{
  eepromerror = 0;
  unsigned long b = 0;
  unsigned int temp;
  for (int i = 0; i < 18; i++)
  {
    b = b + EEPROM.read(i);
  }
  if (b == 4590)
  {
    temp = EEPROM.read(0);
    EEPROM.write(0, 0);
    if (EEPROM.read(0) != 0)
    {
      eepromerror = 1;
    }
    EEPROM.write(0, temp);
  }
}

int button() // 0: Geçerli tuş yok. 1: Mode1. 2: Mode2. 3: Decrease. 4: Increase. 5: Done.
{
  key1 = buttonbas();
  key2 = debouncebutton();
  if ((key1 == key2) && ((key1 * key2) != 0))
  {
    return key1;
  }
  return 0;
}

int buttonbas()
{
  keypress = PINC & B00000111;
  for (int n = 0; n < 100; n++)
  {
    keypress &= PINC;
  }
  if (keypress == B00000100) return 4;
  if (keypress == B00000110) return 1;
  if (keypress == B00000101) return 2;
  if (keypress == B00000011) return 3;
  return 0;
}

int debouncebutton() //Buraya gelirken key1 değişkeni basıldığı belirlenen butonu içeriyor. Yani 0 - 5 arası bir değer.
{
  if (key1 == 0) return key1; //Tuşa basılmamış ise hiçbir şey yapmadan geri dön
  b = 0; //Sayaç sıfırlanıyor
  for (int n = 0; n < debounce; n++)
  {
    key = buttonbas(); //Butonlar "debounce" kez okunuyor
    if (key == key1) b++; //Eğer okunan değer ilk okunan değer ile aynı ise b sayacı bir artırılıyor
    else if (key != 0) return 0; //Farklı bir değer okunduysa ve bu değer 0 değil ise bu durum bounce nedeniyle değil başka butona basma nedeniyle olmuştur. 0 döndürüyoruz.
  }
  if (b < bounce) return 0; //Okunan değerlerin en az % 80'i key1 ile aynı olmalı. Yoksa 0 döndürüyoruz
  while (buttonbas() != 0) //Buraya geldiğimize göre "debounce" test okumasındaki değerlerin en az "bounce"'ı orijinal key1 değeri ile aynı demektir. Artık butonun bırakılmasını bekliyor ve key1 değerini döndürüyoruz
  {
  }
  return key1;
}


void flashleds()
{
  digitalWrite(servo1LED, HIGH);
  delay(200);
  digitalWrite(servo1LED, LOW);

  digitalWrite(servo2LED, HIGH);
  delay(200);
  digitalWrite(servo2LED, LOW);

  digitalWrite(servo3LED, HIGH);
  delay(200);
  digitalWrite(servo3LED, LOW);
}

void flashleds2() //Tüm LED'leri birlikte beş kez hızlıca yakıp söndüren işlev
{
  for (int n = 0; n < 5; n++)
  {
    digitalWrite(servo1LED, HIGH);
    digitalWrite(servo2LED, HIGH);
    digitalWrite(servo3LED, HIGH);
    delay(200);
    digitalWrite(servo1LED, LOW);
    digitalWrite(servo2LED, LOW);
    digitalWrite(servo3LED, LOW);
    delay(200);
  }
}
 
Bence de çok ilginç bir programlama tekniği, o kadar uzun kodu array kullanmadan ama buna rağmen kendi timer kütüphenesini oluşturarak yazmak ... :laugh: . Sümer abi , "free sample" alabliyor muyuz ? :D
 
Servo senkronizasyon modülü

Tümü free zaten. :)
Bak kodun en büyük numarasını açıklayayım: Interrupt sırasında servo çıkışı vs için kullanılacak değişkenler ana loop içinde hesaplanırken kısa süreliğine interruptlar engelleniyor. İnanılmaz önemli bir ayrıntı.
 
Servo senkronizasyon modülü

İnsan bazen çok dar görüşlü oluyor.
Benim tasarladığım sistemde üç servo kullanılabiliyor en fazla. Yani her bir aileron için üç servo olabiliyor. Bu durum ne kadar sıklıkla görülebilir? Çok nadir! Ama iki kanatta ikişerden dört servo olur mu? Olur. O durumda bu modülden iki tane gerekiyor. Yanlış bir yaklaşım. Çünkü bu modülü 4 servolu yaparsak tek modülle iki kanadı da halledebiliyoruz. Neyse ki çok geç olmadan farkedip dört kanallıyı da hazırladım. Sanıyorum çok daha efektif bir kullanım sağlayacak.
 
Servo senkronizasyon modülü

Sümer Yamaner' Alıntı:
...... Neyse ki çok geç olmadan farkedip dört kanallıyı da hazırladım. Sanıyorum çok daha efektif bir kullanım sağlayacak.
Desene abi, yine elinden kurtulamamış :laugh:
 
Elimden kurtulup kurtulmaması değil de gerçekten de bir şeyler yaptıkça yeni şeyler çıkıyor ortaya.
Dört servonun sinyal çıkışı için geçen süre toplamda 4 ile 8 milisaniye arasında değişiyor. Çünkü her bir servoya diğerinden sonra sinyal gönderiliyor. Her 20 milisaniyede bir 8 milisaniyelik bir duraklama oluyor ana program akışında. Dün gece kafamda oluşturduğum yeni bir algoritma ile çalışmaya başlayacağım. Eğer istediğimi becerebilirsem servo sinyallerini eşzamanlı olarak vereceğim. Dolayısıyla interruptta geçen süre en fazla iki milisaniye kadar olacak. Ya da az daha fazla. İşte bu gerçekten ilginç bir kod olacak! :D :)
 
Servo senkronizasyon modülü

Sümer Yamaner' Alıntı:
Buyurun, demo videomuz...
Abi teşekkür ederiz, ellerine sağlık, kırmadın özel olarak bizler için demo videosu çektin :thumbup: Setup modu, ledli gösterge ile gerçekten güzel bir çalışma oldu.

Bu arada bu kadar başarılı olmanın sırrını çözdüm abi, Kontrol mühendisi :laugh: Maşallahı var, işini gerçekten çok ciddiye alıyor. Sen izin verip masadan gönderiyorsun ama o kaşla göz arasında tekrardan işinin başına dönüyor :D
 
Servo senkronizasyon modülü

Hatırlarsan geçen yıl Sea Fury'yi toplarken de başka bir kontrol mühendisim vardı. O terfi etti. Başmühendis oldu. Artık masa başında takılıyor. Bunu da çömez olarak gönderdi. Ama bu ondan kötü çıktı. Her yeri kurcalıyo! :D
 
Servo senkronizasyon modülü

Sümer Yamaner' Alıntı:
Hatırlarsan geçen yıl Sea Fury'yi toplarken de başka bir kontrol mühendisim vardı. O terfi etti. Başmühendis oldu. Artık masa başında takılıyor. Bunu da çömez olarak gönderdi. Ama bu ondan kötü çıktı. Her yeri kurcalıyo! :D
Hatırlamam mı. Ama söylemesen aynı mühendis diye düşünmüştüm :D
 
Servo senkronizasyon modülü

Sümer abi ellerine sağlık. İlk etapta bu modüle ne gerek var ki, kumandadan zaten ayarlanıyor bunlar diye düşünmüştüm, tabi ben aynı iş için birden fazla servo kullanmaktan bihaber olduğum için... Şimdi videoyu da izleyince kavradım olayı. Çok faydalı bir eser olmuş :D