Ekranlı Servo Tester

  • Forumdan daha fazla yararlanmak için buradan ÜYE olunuz

    Eğer eski üyemizseniz, MEVCUT Kullanıcı ADI ve ŞİFRENİZİ aynen kullanabilirsiniz. Eğer girişte sorun yaşıyorsanız, lütfen şu konuya TIKLAYINIZ.
Katılım
17 Eyl 2013
Mesajlar
4,803
Beğeniler
9,428
Yaş
56
Konum
İstanbul
Web sitesi
www.sumeryamaner.com
İlgi Alanı
Uçak
#76
Yahu kulaklarım o kadar çok çınladı ki ancak yeni kendime gelebildim. Sümer abi,

hani hazır yazılmış kodu kütüphane haline getireceğimden değil ama :evil: gene de kodunu görebilsek ne güzel olurdu diyorum :D ... Ne bileyim, koda yorum olarak eklenmiş "şuraya deadband ekledim", "şurada titreşimi kaldırdım", "burada interruptlara şöyle yaptım" gibi satırlarda olsa, hani olmazda, kodu hızlı bir şekilde kütüphane haline getireceklere kolaylık olurdu ...

Bu arada eline sağlık Sümer abi :D ...
Hemen geliyor. En son modelimizin (7 segment LED göstergeli) kodu: (Yorumlar yetersiz olabilir)

Kod:
/*
   Atmega 328 @ 16MHz external
   Çıkış PD0
   Buton PB0
   Rotary Encoder A PB2 PCINT2
   Rotary Encoder B PD5 PCINT21
   mode0 Center
   mode1 Kaba adımlı Coarse
   mode2 Normal (hassas adımlı) Fine
   mode3 Sweep
   Shift registerli 4 haneli 7 segment display kullanılıyor
   SCLK PC3
   RCLK PC4
   DIO PC5
   Power On sırasında butona basılı ise 760 - 1520 seçimi yapılıyor
*/


#define buttonpin 8
#define rotaryA 10
#define rotaryB 5
#define pwmpin 0
#define SCLK 17
#define RCLK 18
#define DIO 19

volatile unsigned int pwm = 1520;
volatile unsigned int dolgu;
unsigned int prevpwm = 1520;
unsigned int oldpwm = 1520;
boolean button;
byte mode;
byte stp = 5;
boolean dir = 1;
volatile boolean pwmon;
volatile boolean slow = 1; // 1: 1520 uS, 0: 760 uS
volatile boolean rA;
volatile boolean rB;

volatile byte pointer;
byte bitmap[10]; // 7 segment digit datasını tutuyor
byte buf[4]; // Devir değerini alfanümerik olarak tutuyor
volatile byte prtbuf[4]; // Devir değerinin digit datasına çevrilmiş halini tutuyor
byte rowbyte;

byte sweeppointer;
byte sweeppointercounter;
byte sweepfactor;

boolean working;


ISR(TIMER1_COMPA_vect)
{
  digitalWrite(pwmpin, LOW);
  if (pwmon)
  {
    pwmon = 0;
    TCNT1 = 0;
    OCR1A = dolgu * (slow + 1);
  }
  else
  {
    pwmon = 1;
    digitalWrite(pwmpin, HIGH);
    TCNT1 = 0;
    OCR1A = pwm * (slow + 1);
  }
}

ISR(TIMER2_OVF_vect)
{
  sei(); // İşte meşhur titreşim önleyici satır! Interrupt içinde interrupt açılıyor.
  TCNT2 = 17;
  LED_OUT(prtbuf[pointer]);
  switch (pointer)
  {
    case 0:
      LED_OUT(8);
      break;
    case 1:
      LED_OUT(4);
      break;
    case 2:
      LED_OUT(2);
      break;
    case 3:
      LED_OUT(1);
      break;
  }
  digitalWrite(RCLK, LOW);
  digitalWrite(RCLK, HIGH);
  pointer++;
  if (pointer > 3) pointer = 0;
}


ISR(PCINT0_vect)
{
  rA = digitalRead(rotaryA);
  rB = digitalRead(rotaryB);
  if (rA)
  {
    if ((mode == 1) || (mode == 2)) //  coarse / fine
    {
      if (rA == rB)
      {
        if (mode == 2) pwm--;
        if (mode == 1) pwm = pwm - 8;
      }
      else
      {
        if (mode == 2) pwm++;
        if (mode == 1) pwm = pwm + 8;
      }
    }
    if (mode == 3) // sweep
    {
      if (rA == rB)
      {
        stp--;
        if (stp < 1) stp = 1;
      }
      else
      {
        stp++;
        if (stp > 20) stp = 20;
      }
    }
  }
}

void setup()
{
  pinMode(buttonpin, INPUT_PULLUP);
  pinMode(rotaryA, INPUT_PULLUP);
  pinMode(rotaryB, INPUT_PULLUP);
  pinMode(pwmpin, OUTPUT);
  pinMode(RCLK, OUTPUT);
  pinMode(SCLK, OUTPUT);
  pinMode(DIO, OUTPUT);
  bitmap[0] = B11000000;
  bitmap[1] = B11111001;
  bitmap[2] = B10100100;
  bitmap[3] = B10110000;
  bitmap[4] = B10011001;
  bitmap[5] = B10010010;
  bitmap[6] = B10000010;
  bitmap[7] = B11111000;
  bitmap[8] = B10000000;
  bitmap[9] = B10010000;
  oldpwm = pwm;
  cli();
  TCCR1A = 0;
  TCCR1B = B00000010; // Timer1 prescaler 8
  TCCR1C = 0;
  TCCR2A = 0;
  TCCR2B = B00000100; // Timer2 prescaler 256
  TIMSK1 = 2; // OCR1A interrupt enabled
  TIMSK2 = 1; // Timer2 overflow interrupt enabled
  PCICR = 1; // PCINT0 Enabled
  PCMSK0 = B00000100; // PCI2 enabled (PB2, Arduino 10)
  sei();
  if (!digitalRead(buttonpin))
  {
    delay(10);
    if (!digitalRead(buttonpin)) changespeed();
    while (!digitalRead(buttonpin));
  }
}

void loop()
{
  working = 1;
  if (pwm < 800) pwm = 800;
  if (pwm > 2200) pwm = 2200;
  button = digitalRead(buttonpin);
  if (!button)
  {
    delay(10);
    button = digitalRead(buttonpin);
    if (!button) changemode();
  }
  if (mode == 3)
  {
    printout(stp);
  }
  else
  {
    if(slow)
    {
      printout(pwm);
    }
    else
    {
      printout(pwm / 2);
    }
  }
  switch (mode)
  {
    case 0:
      midoutput();
      break;
    case 1:
      normaloutput();
      break;
    case 2:
      normaloutput();
      break;
    case 3:
      sweep();
      break;
  }
}

void normaloutput()
{
  dolgu = 20000 - pwm;
}

void midoutput()
{
  pwm = 1520;
  dolgu = 18480;
}

void sweep()
{
  if (dir)
  {
    pwm = prevpwm + stp;
    if (pwm > 2200)
    {
      pwm = 2200;
      dir = 0;
    }
  }
  else
  {
    pwm = prevpwm - stp;
    if (pwm < 800)
    {
      pwm = 800;
      dir = 1;
    }
  }
  prevpwm = pwm;
  dolgu = 20000 - pwm;
  delay(10);
}

void changemode()
{
  mode++;
  if (mode > 3) mode = 0;
  if (mode == 3) oldpwm = pwm;
  if (mode == 1) pwm = oldpwm;
  delay(10);
  while (!digitalRead(buttonpin));
}

void changespeed()
{
  while (!digitalRead(buttonpin)); // Buton bırakılana kadar bekliyoruz
  delay(10); // Debounce
  while (!digitalRead(buttonpin)); // Buton bırakılana kadar bekliyoruz
  while (digitalRead(buttonpin))
  {
    if (slow)
    {
      printout(1520);
    }
    else
    {
      printout(760);
    }
    if (digitalRead(rotaryB))
    {
      delay(10);
      if (digitalRead(rotaryB))
      {
        slow = !slow;
        while (digitalRead(rotaryB))
        {
          if (!digitalRead(buttonpin))
          {
            slow = !slow;
            return;
          }
        }
      }
    }
  }
}


void printout(unsigned int x)
{
  buf[0] = x / 1000;
  buf[1] = (x - 1000 * buf[0]) / 100;
  buf[2] = (x - 1000 * buf[0] - 100 * buf[1]) / 10;
  buf[3] = x % 10;
  if (buf[0] == 0)
  {
    buf[0] = 255;
    if (buf[1] == 0)
    {
      buf[1] = 255;
      if (buf[2] == 0) buf[2] = 255;
    }
  }
  for (int n = 0; n < 4; n++)
  {
    if (buf[n] < 10)
    {
      prtbuf[n] = bitmap[buf[n]];
    }
    else
    {
      prtbuf[n] = 255;
    }
  }
  dp_OFF();
  if (working)
  {
    if (mode < 3)
    {
      dp_SET(mode);
    }
    else // Sweep modunda Decimal Point hareketli
    {
      sweeppointercounter++;
      sweepfactor = map(stp, 1, 20, 75, 30); // Decimal Point hareket hızını belirliyor
      if (sweeppointercounter > sweepfactor)
      {
        sweeppointercounter = 0;
        sweeppointer++;
        if (sweeppointer > 3) sweeppointer = 0;
      }
      dp_SET(sweeppointer);
    }
  }
}

void LED_OUT(unsigned char X)
{
  unsigned char i;
  for (i = 8; i >= 1; i--)
  {
    if (X & 0x80)
    {
      digitalWrite(DIO, HIGH);
    }
    else
    {
      digitalWrite(DIO, LOW);
    }
    X <<= 1;
    digitalWrite(SCLK, LOW);
    digitalWrite(SCLK, HIGH);
  }
}

void dp_OFF()
{
  for (int m = 0; m < 4; m++)
    prtbuf[m] |= B10000000; // All Decimal Points OFF
}

void dp_SET(byte z)
{
  prtbuf[z] &= B01111111; // Selected Decimal Point ON
}
 
Katılım
17 Eyl 2013
Mesajlar
4,803
Beğeniler
9,428
Yaş
56
Konum
İstanbul
Web sitesi
www.sumeryamaner.com
İlgi Alanı
Uçak
#78
Al işte, işin yoksa kütüphaneyi tık tık yerine koymak yerine ISR içinde niye sei() kullanılır diye oku...
Yahu elalemin yazdığı ne idüğü belirsiz kütüphaneyi niye koyayım oraya ki?! :p
Zavallı Atmega'ya üç interrupt birden yüklemişim zaten. Var mı bunu yapacak library!? :D
 

Zafer ŞAHİN

Mahna Mahna ...
Katılım
29 Ağu 2013
Mesajlar
1,302
Beğeniler
2,096
Yaş
42
Konum
Elektronik ve Haberleşme Mühendisi
Web sitesi
www.milidiabilisim.com
İlgi Alanı
Multikopter
#79
Yahu elalemin yazdığı ne idüğü belirsiz kütüphaneyi niye koyayım oraya ki?! :p
Zavallı Atmega'ya üç interrupt birden yüklemişim zaten. Var mı bunu yapacak library!? :D
Abi zaten ben bunu sana değil kendime söylüyorum. Bunu yapacak bir libray yok, gıcıklığına oturmuş bunu Sümer abi yapmış, bu kodu kütüphaneye çevirebilmem için ISR içinde niye tekrar interrupt açılması gerektiğini, ya da ne zaman açılması gerektiğini okuyup anlamam gerekiyor.
 
Katılım
17 Eyl 2013
Mesajlar
4,803
Beğeniler
9,428
Yaş
56
Konum
İstanbul
Web sitesi
www.sumeryamaner.com
İlgi Alanı
Uçak
#80
Abi zaten ben bunu sana değil kendime söylüyorum. Bunu yapacak bir libray yok, gıcıklığına oturmuş bunu Sümer abi yapmış, bu kodu kütüphaneye çevirebilmem için ISR içinde niye tekrar interrupt açılması gerektiğini, ya da ne zaman açılması gerektiğini okuyup anlamam gerekiyor.
Üç interrupttan biri time critical, (PWM darbesini oluşturan) diğer ikisi (rotary encoderi okuyan ve 7 segment göstergeyi süren) çok az time ciritical. O nedenle daha az time critical olanların ISR'lerinde interruptları açmak lazım ki üretilen PWM darbesinin süresinde oynama olmasın. Yani aslında diğer ISR'nin başına da sei(); komutunu yazmam lazımdı. Ancak butonu çevirirken oluşacak titreşim pek farkedilmediği için bu hali ile de çalışıyor.
Ama display sürülmesi sürekli yapıldığı için sık sık çakışma olabiliyordu ve gerçekten de servo titriyordu. Tek satır işi bitirdi. :)
 
Beğeniler: Ali Emre KAYGIN

Benzer Konular