Arduino ile Multithreading Zamanlı Röle Kontrolü (arduino millis)

Bu yazımda Arduino kullanarak 3 farklı röleyi 3 farklı butona basıldığı anda belirli bir zaman çalıştırıp daha sonra kapatacak bir uygulama yapacağız, fakat bu işlemleri aynı anda yapabilmesini sağlamak için de millis() fonksiyonunu kullanacağız. Kısacası Arduino millis nedir yazımızda 🙂

Arduino milis

Not: Gelen tepkiler nedeniyle bu uyarıyı yazmam gerekti, başlıkta multithreading yazdığım için Arduino ile multithread yapılamayacağı konusunda tepkiler vardı, evet bunun zaten mümkün olmadığını bildiğim için ve zaten bu yüzden Arduino ile nasıl birden çok işi yaptırabilirizi açıklayan bir yazıyı yazmam gerekti, multithread burada sadece birden çok işi aynı anda yapmak için kullanılan genel bir ifade olması nedeniyle kullanıldı, aksini yani çok çekirdekli işlemciler ve işletim sistemi gereksinimlerini iddia etmek zaten büyük hata olacaktır. Ayrıca zaten bu özelliklerde bir cihaz olmadığı için de aynı anda birden çok işlemi gerçekten yapamaz sadece yapıyormuş gibi görünür, bizim algılayabileceğimizden daha hızlı bir işlem hızıyla sırayla isteklerimizi yapar.

Arduino‘da örneğin bir röleyi açıp 1 dk. sonra kapatmak istediğimiz de eğer 1 dk. beklemek için delay kullanırsak bu artık bu süre bitene kadar başka hiç bir işlem yapamayacağımız anlamına geliyor, fakat biz 1. butona basıp röleyi çektikten sonra süresi bitmeden başka bir cihazı çalıştırmak için başka bir butona ile başka bir röleyi daha çektirmek isteyebiliriz, delay bunu imkansız kılar fakat millis kullandığımız da artık istediğimiz işlemi yapabilir oluruz.

Millis fonksiyonu aslında Arduino‘nun çalışma süresini milisaniye olarak tutar, Arduino çalışmaya başladığı anda zamanı tutmaya başlar ve fonksiyonu çağırdığımız da bize kaç milisaniye süresince çalıştığını döndürür.

Arduino millis

Şimdi Arduino milis kodumuzu yazmaya başlayalım, örnek senaryomuz da 3 rölemiz mevcut ve bunları kontrol edeceğimiz 3 adet butonumuz var, butonlarımız push buton.

Değişkenlerimiz;

Öncelikle Rölelerimizi kontrol edeceğimiz pinleri tanımlıyoruz;

const int RELAY1 = 12;
const int RELAY2 = 11;
const int RELAY3 = 10;

Aynı şekilde butonlarımızı Arduino‘da taktığımız pinleri tanımlıyoruz;

const int BUTTON1 = 2;
const int BUTTON2 = 3;
const int BUTTON3 = 4;

Butonlarımızın son durumu ve şimdi ki durumlarını tutacağımız değişkenleri tanımıyoruz, ayrıca röle durumlarını tutacağımız değişkenlerimizide her röle için tanımlıyoruz.

boolean lastButton1 = LOW;
boolean currentButton1 = LOW;
boolean relayOn1 = true;
boolean lastButton2 = LOW;
boolean currentButton2 = LOW;
boolean relayOn2 = true;
boolean lastButton3 = LOW;
boolean currentButton3 = LOW;
boolean relayOn3 = true;

Başlangıç durumu, çalışma durumu ve anlık çalışma süresini (yani butona basıldığı andan itibaren millis’den alacağımız değerleri) tutacağımız değişkenleri tanımlıyoruz,

boolean b1Start = false;
int b1Stage = -1;
unsigned long b1P1WorkingMillis = 0;


boolean b2Start = false;
int b2Stage = -1;
unsigned long b2P1WorkingMillis = 0;


boolean b3Start = false;
int b3Stage = -1;
unsigned long b3P1WorkingMillis = 0;

Butona basıldığında rölelerimizin ne kadar süre çekileceğini tutacak değişkenimizi tanımlıyoruz. Değer milisaniye olacaktır, ben 3000 olarak tanımladım, 3 saniye boyunca rölemiz çekili kalacak.

const long p1WorkingInterval = 3000;

Şimdi void setup() fonksiyonuna butonlarımızı input, röle pinlerimizide output olduğunu belirtiyoruz, ayrıca röle çıkışlarını başlangıç durumlarını ayarlıyoruz.

void setup(){
  Serial.begin(9600); // See the connection status in Serial Monitor
  pinMode(RELAY1, OUTPUT);
  pinMode(BUTTON1, INPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(BUTTON2, INPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(BUTTON3, INPUT);

  digitalWrite(RELAY1, true);
  digitalWrite(RELAY2, true);
  digitalWrite(RELAY3, true);
}

Buton durumlarımızı takip edip değiştiren fonksiyonlarımızı ekliyoruz;

boolean debounce1(boolean last1) {
  boolean current1 = digitalRead(BUTTON1);
  if(last1 != current1) {
    delay(5);
    current1 = digitalRead(BUTTON1);
  }
  return current1;
}
boolean debounce2(boolean last2) {
  boolean current2 = digitalRead(BUTTON2);
  if(last2 != current2) {
    delay(5);
    current2 = digitalRead(BUTTON2);
  }
  return current2;
}
boolean debounce3(boolean last3) {
  boolean current3 = digitalRead(BUTTON3);
  if(last3 != current3) {
    delay(5);
    current3 = digitalRead(BUTTON3);
  }
  return current3;
}

voip loop() fonksiyonumuzun içeriğine geçmeden önce butonlara basıldıktan sonra yapılacak işlemler için gerekli fonksiyonları yazacağız.

Fonksiyon içeriğini inceleyecek olursak nowMillis tanımlıyoruz bu millis() fonksiyonunun o anki değerini tutacağımız ve çalışma değerimize geldiğinde röleyi durdurmamızda kontrol edeceğimiz değişkendir.

Butona basıldığını anladığımız anda buton stage değiştiyor ve çalışma süresince röleyi çektikten sonra yine statüleri değiştirerek röleyi kapatıyoruz.

Bu işlemler esnasında da seri porta röle çekildi ve röle kapandı şeklinde yazdırıyoruz.

void B1Function()
{
  unsigned long nowMillis = 0;
  
  currentButton1 = debounce1(lastButton1);
  if(lastButton1 == LOW && currentButton1 == HIGH) {
    if (!b1Start)
    {
      b1Start = true;
      b1Stage = 0;
    }
  }
  lastButton1 = currentButton1;
  
  if (b1Start)
  {
    switch (b1Stage)
    {
      case 0:
        b1Stage = 1;
        digitalWrite(RELAY1, false);
        Serial.println("1.Röle Çekildi");
        b1P1WorkingMillis = millis();
        break;
      case 1:
        nowMillis = millis();
        if (nowMillis - b1P1WorkingMillis >= p1WorkingInterval)
        {
          b1Stage = -1;
          b1Start = false;
          Serial.println("1. Röle Kapandı!");
          digitalWrite(RELAY1, true);
        }
  
    }  
  }
}

void B2Function()
{
  unsigned long nowMillis = 0; 
  currentButton2 = debounce2(lastButton2);
  if(lastButton2 == LOW && currentButton2 == HIGH) {
    if (!b2Start)
    {
      b2Start = true;
      b2Stage = 0;
    }
  }
  lastButton2 = currentButton2;
  
  if (b2Start)
  {
    switch (b2Stage)
    {
      case 0:
        b2Stage = 1;
        digitalWrite(RELAY2, false);
        Serial.println("2. Röle Çekildi");
        b2P1WorkingMillis = millis();
        break;
      case 1:
        nowMillis = millis();
        if (nowMillis - b2P1WorkingMillis >= p1WorkingInterval)
        {
          b2Stage = -1;
          b2Start = false;
          Serial.println("2. Röle Kapandı!");
          digitalWrite(RELAY2, true);
        }
    }  
  }
}


void B3Function()
{
  unsigned long nowMillis = 0; 
  currentButton3 = debounce3(lastButton3);
  if(lastButton3 == LOW && currentButton3 == HIGH) {
    if (!b3Start)
    {
      b3Start = true;
      b3Stage = 0;
    }
  }
  lastButton3 = currentButton3;
  
  if (b3Start)
  {
    switch (b3Stage)
    {
      case 0:
        b3Stage = 1;
        digitalWrite(RELAY3, false);
        Serial.println("3. Röle Çekildi");
        b3P1WorkingMillis = millis();
        break;
      case 1:
        nowMillis = millis();
        if (nowMillis - b3P1WorkingMillis >= p1WorkingInterval)
        {
          b3Stage = -1;
          b3Start = false;
          Serial.println("3. Röle Kapandı!");
          digitalWrite(RELAY3, true);
        }
    }  
  }
}

Son olarak da, voip loop() fonksiyonumuz içerisine bu 3 buton için yazdığımız fonksiyonları çağırıyoruz, böylece loop içerisinde devamlı olarak buton basılmış mı diyerek kontrol ediyor ve basıldığı anda fonksiyon içerisindeki işlemleri yaptırıyoruz.

void loop()
 {
   B1Function();
   B2Function();
   B3Function();
 }

Kodlarımız en son aşağıdaki gibi görünecektir.

const int RELAY1 = 12;
const int RELAY2 = 11;
const int RELAY3 = 10;

const int BUTTON1 = 2;
const int BUTTON2 = 3;
const int BUTTON3 = 4;

boolean lastButton1 = LOW;
boolean currentButton1 = LOW;
boolean relayOn1 = true;
boolean lastButton2 = LOW;
boolean currentButton2 = LOW;
boolean relayOn2 = true;
boolean lastButton3 = LOW;
boolean currentButton3 = LOW;
boolean relayOn3 = true;

boolean b1Start = false;
int b1Stage = -1;
unsigned long b1P1WorkingMillis = 0;


boolean b2Start = false;
int b2Stage = -1;
unsigned long b2P1WorkingMillis = 0;


boolean b3Start = false;
int b3Stage = -1;
unsigned long b3P1WorkingMillis = 0;

const long p1WorkingInterval = 3000;


void setup(){
  Serial.begin(9600); // See the connection status in Serial Monitor
  pinMode(RELAY1, OUTPUT);
  pinMode(BUTTON1, INPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(BUTTON2, INPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(BUTTON3, INPUT);

  digitalWrite(RELAY1, true);
  digitalWrite(RELAY2, true);
  digitalWrite(RELAY3, true);
}

boolean debounce1(boolean last1) {
  boolean current1 = digitalRead(BUTTON1);
  if(last1 != current1) {
    delay(5);
    current1 = digitalRead(BUTTON1);
  }
  return current1;
}
boolean debounce2(boolean last2) {
  boolean current2 = digitalRead(BUTTON2);
  if(last2 != current2) {
    delay(5);
    current2 = digitalRead(BUTTON2);
  }
  return current2;
}
boolean debounce3(boolean last3) {
  boolean current3 = digitalRead(BUTTON3);
  if(last3 != current3) {
    delay(5);
    current3 = digitalRead(BUTTON3);
  }
  return current3;
}

void loop()
{
  B1Function();
  B2Function();
  B3Function();
}

void B1Function()
{
  unsigned long nowMillis = 0;
  
  currentButton1 = debounce1(lastButton1);
  if(lastButton1 == LOW && currentButton1 == HIGH) {
    if (!b1Start)
    {
      b1Start = true;
      b1Stage = 0;
    }
  }
  lastButton1 = currentButton1;
  
  if (b1Start)
  {
    switch (b1Stage)
    {
      case 0:
        b1Stage = 1;
        digitalWrite(RELAY1, false);
        Serial.println("1.Röle Çekildi");
        b1P1WorkingMillis = millis();
        break;
      case 1:
        nowMillis = millis();
        if (nowMillis - b1P1WorkingMillis >= p1WorkingInterval)
        {
          b1Stage = -1;
          b1Start = false;
          Serial.println("1. Röle Kapandı!");
          digitalWrite(RELAY1, true);
        }
  
    }  
  }
}

void B2Function()
{
  unsigned long nowMillis = 0; 
  currentButton2 = debounce2(lastButton2);
  if(lastButton2 == LOW && currentButton2 == HIGH) {
    if (!b2Start)
    {
      b2Start = true;
      b2Stage = 0;
    }
  }
  lastButton2 = currentButton2;
  
  if (b2Start)
  {
    switch (b2Stage)
    {
      case 0:
        b2Stage = 1;
        digitalWrite(RELAY2, false);
        Serial.println("2. Röle Çekildi");
        b2P1WorkingMillis = millis();
        break;
      case 1:
        nowMillis = millis();
        if (nowMillis - b2P1WorkingMillis >= p1WorkingInterval)
        {
          b2Stage = -1;
          b2Start = false;
          Serial.println("2. Röle Kapandı!");
          digitalWrite(RELAY2, true);
        }
    }  
  }
}


void B3Function()
{
  unsigned long nowMillis = 0; 
  currentButton3 = debounce3(lastButton3);
  if(lastButton3 == LOW && currentButton3 == HIGH) {
    if (!b3Start)
    {
      b3Start = true;
      b3Stage = 0;
    }
  }
  lastButton3 = currentButton3;
  
  if (b3Start)
  {
    switch (b3Stage)
    {
      case 0:
        b3Stage = 1;
        digitalWrite(RELAY3, false);
        Serial.println("3. Röle Çekildi");
        b3P1WorkingMillis = millis();
        break;
      case 1:
        nowMillis = millis();
        if (nowMillis - b3P1WorkingMillis >= p1WorkingInterval)
        {
          b3Stage = -1;
          b3Start = false;
          Serial.println("3. Röle Kapandı!");
          digitalWrite(RELAY3, true);
        }
    }  
  }
}

Buradaki Arduino milis uygulamasının .ino dosyasına Github adresimden ulaşabilirsiniz.

Exit mobile version