Arduino millis() konusunda yardıma ihtiyacım var.

Gokrtl

Gökhan Kartal (TeknoDay)
Staff member
Katılım
27 Şubat 2019
Mesajlar
11,215
Şu millisi bir türlü oturtamadım kafada. Ne kalın kafam var yav.:kizgin3:

Bu aşağıdaki kodu normalde çalıştırabiliyorum ama butona basılınca çalışsın istiyorum, çalışmıyor.
Kurcaladıkça da yandı gene beyin.

millis():
  if (digitalRead(dk15)) {
  digitalWrite(role, HIGH);
   simdikiZaman = millis();
    if (simdikiZaman - oncekiZaman >= zaman15) {
      digitalWrite(role, LOW);
      simdikiZaman = oncekiZaman ;
    }
  }
 
Yav kafayı yicem. Röleyi 5sn sonra kapat diyorum kapatmıyor :kizgin2:

millis.PNG


C:
#define role 0
#define dk15 4

unsigned long simdikiZaman;
unsigned long oncekiZaman = 0;
const int zaman15 = 5000; //900,000 15dk

void setup() {
  Serial.begin(9600);
  pinMode(dk15, INPUT);
  pinMode(role, OUTPUT);

}

void loop() {
  simdikiZaman = millis(); // Zamanı tut
  if (digitalRead(dk15)) { // Butona basıldıysa
    digitalWrite(role, HIGH); // Röleyi aktif et
    Serial.print("role durum 1: ");
    Serial.println(digitalRead(role));
    if (simdikiZaman - oncekiZaman >= zaman15) { // 5 saniye geçtiyse
      digitalWrite(role, LOW); // Röleyi kapat
      Serial.print("role durum 2: ");
      Serial.println(digitalRead(role));
      delay(10000);
      oncekiZaman = simdikiZaman; // şimdiki zamanı önceki zamana eşitle
      Serial.println(oncekiZaman);
    }
  }
}
 
Ne yapmak istediğini anlamadım ama aşağıdaki gibi çalışır.

C++:
15_basildi_mi = digitalRead(dk15);
if (15_basildi_mi == HIGH) {
    digitalWrite(role, HIGH);
    simdikiZaman = millis();
    if (simdikiZaman - oncekiZaman <= zaman15) {
        digitalWrite(role, LOW);
        simdikiZaman = oncekiZaman ;
    } else {
        
    }
} else {
    
}
 
Ne yapmak istediğini anlamadım ama aşağıdaki gibi çalışır.

C++:
15_basildi_mi = digitalRead(dk15);
if (15_basildi_mi == HIGH) {
    digitalWrite(role, HIGH);
    simdikiZaman = millis();
    if (simdikiZaman - oncekiZaman <= zaman15) {
        digitalWrite(role, LOW);
        simdikiZaman = oncekiZaman ;
    } else {
      
    }
} else {
  
}
Yapmak istediğim şey çok basit.
Butona basınca 5sn röleyi çekecek, sonra bırakacak. Bu kadar.

Senin kodda butona basınca hep açık kalıyor.
 
Son düzenleme:
Çözüm basit, roleyi bıraktığında butona basılıyor mu diye tekrar kontrol edersin...

C++:
15_basildi_mi = digitalRead(dk15);

if (15_basildi_mi == HIGH) {
    digitalWrite(role, HIGH);
    simdikiZaman = millis();
    if (simdikiZaman - oncekiZaman >= zaman15) {
        digitalWrite(role, LOW);
        simdikiZaman = oncekiZaman ;
        15_basildi_mi = digitalRead(dk15); // LOW olacağı için tekrar butona basana kadar ilk if'in içine uğramaz.
    } else {
    }
} else {
    
}
 
Çözüm basit, roleyi bıraktığında butona basılıyor mu diye tekrar kontrol edersin...

C++:
15_basildi_mi = digitalRead(dk15);

if (15_basildi_mi == HIGH) {
    digitalWrite(role, HIGH);
    simdikiZaman = millis();
    if (simdikiZaman - oncekiZaman >= zaman15) {
        digitalWrite(role, LOW);
        simdikiZaman = oncekiZaman ;
        15_basildi_mi = digitalRead(dk15); // LOW olacağı için tekrar butona basana kadar ilk if'in içine uğramaz.
    } else {
    }
} else {
   
}
Yok yine açık kalıyor. Low'a çekmiyor bir türlü.
Senden kopyaladığım ile bendekinin birleşimi şöyle;
(değişkenlerin başında 15 rakamı bende kabul etmediği için sildim)

C:
#define role 7
#define dk15 4

unsigned long simdikiZaman;
unsigned long oncekiZaman = 0;
const int zaman15 = 5000; //900,000 15dk
int basildi_mi;
void setup() {
  Serial.begin(9600);
  pinMode(dk15, INPUT);
  pinMode(role, OUTPUT);

}

void loop() {
  basildi_mi = digitalRead(dk15);

  if (basildi_mi == HIGH) {
    digitalWrite(role, HIGH);
    simdikiZaman = millis();
    if (simdikiZaman - oncekiZaman >= zaman15) {
      digitalWrite(role, LOW);
      simdikiZaman = oncekiZaman ;
      basildi_mi = digitalRead(dk15); // LOW olacağı için tekrar butona basana kadar ilk if'in içine uğramaz.
    } else {
    }
  } else {

  }
}
 
Gecenin 05:00'in de sanırım sorunu buldum.
Youtube da video sahibi Attiny13A entegreyi programlarken "1.2Mhz"'i seçiyordu, bende öyle yapıp yükledim.
Bu şekilde olunca 15dk verdiğim "delay" komutları bile 30sn de kendini kapatıyordu.
Bende internal olarak seçebileceğim en yüksek değer olan 9.6MHz'i seçip yükledim. Böylece 15dk verdiğim "delay" komutu 6 dakika kadar dayandı ama yine menzile ulaşamadı. Sanırım yola Harici kristal bağlayıp devam etmek gerek.

kristal.PNG
 
Zaman farkı hesabı yanlış olmuş Gökhan. Her zaman olmasa da, arada bir gecikme yanlış çıkar. Zaman farkını şöyle bir fonksiyon ile hesapla.

C++:
#include <limits.h>

unsigned int zaman_farki(unsigned int t1, unsigned int t2)
{
    if (t2 >= t1)
    {
        return t2 - t1;
    }
    else
    {
        return t2 + UINT_MAX - t1 + 1;
    }
}

Burada t1 başlangıç zamanı, t2 de şimdiki zaman olarak kullan.
 
Bir de işlemci saat hızı önemli değil, millis fonksiyonu her zaman power geldikten sonra geçen süreyi milisaniye olarak vermesi lazım. Ama işte yukarıdaki gibi taşma durumuna dikkat etmen lazım.
 
Hmm fazla 32/64 bit ile çalışınca alışılıyor :) Arduino'da unsigned int 16 bit. Bu durumda yukarıdaki fonksiyon en fazla 65 saniye işleyebilir. Aşağıdaki gibi yaparsan hesap 32 bit yapılır:

C++:
#include <limits.h>

unsigned long zaman_farki(unsigned long t1, unsigned long t2)
{
    if (t2 >= t1)
    {
        return t2 - t1;
    }
    else
    {
        return t2 + ULONG_MAX - t1 + 1;
    }
}
 
Zaman farkı hesabı yanlış olmuş Gökhan. Her zaman olmasa da, arada bir gecikme yanlış çıkar. Zaman farkını şöyle bir fonksiyon ile hesapla.

C++:
#include <limits.h>

unsigned int zaman_farki(unsigned int t1, unsigned int t2)
{
    if (t2 >= t1)
    {
        return t2 - t1;
    }
    else
    {
        return t2 + UINT_MAX - t1 + 1;
    }
}

Burada t1 başlangıç zamanı, t2 de şimdiki zaman olarak kullan.
Efendim desen yeterdi abi. Başka bir şey soracaktım. :katil1:

Sen bu kristal işlerinden anlarsın.
Aşağıdaki resimde en mantıklı yükleme modu ne olur?
BOD diye bir şey var. 1.8v, 4.8v, 2.7 volt gibi seçenekler var.
Saat hızı için 8, 12, 16, 20 MHz birer tane kristal almıştım ama sen "önemli değil" demişşin. Bende nasıl takacağımı soracaktım :D
Birde zamanlama "Micros Disabled" - "Micros Enabled" seçenekleri var.

İşin özü şu aslında.
4 tane butonum var. 3'ü farklı dakikalarda motoru açıp kapatacak. Dördüncü buton geriye sayımın bitmesini beklemeden motoru durduracak. Bildiğin "Kapat" butonu yani.
Ben normalde delay ile sayımları yaptırabilirdim ama, buton delay süresince çalışmayacağı için bir anlamı olmayacaktı.
O yüzden millis() fonksiyonuna yöneldim. 5dk da bitiririm dediğim işi gece 5'e kadar uğraştırdı ve hala bitmedi.
Son durum olarak şunu düşünüyorum ben bu millis() işini beceremeyip 4 butonu da delay olarak kullansam, kapatmayı da fişi çekerek yapsam diyorum. Bu delayların düzgün sayması için kaç MHz kristal yeter? Veya nasıl bir yol izlemeliyim?
kristal.PNG
 
BOD = brown out detection. Voltaj fazla düşerse işlemci, saçmalayacağına, kendini pasif duruma getirir. Varsayılan ayar neyse orada bırak, sende voltaj düşmeyecek.

ATTiny işlemciyi ben de ayrıntısıyla bilmiyorum, ama "9.6 MHz internal osc" deyince harici kristale gerek olmaz herhalde. İşi görecek en düşük frekansı seçmek lazım. Frekans yükselmesi demek daha fazla parazit demek. Senin devrenin butonlara debounce yapması lazım, bu da kısa zamanda 4 tane butonu sürekli takip etmek demek. O yüzden çok da düşürmek istemiyoruz. Sen 9.6 MHz ile başla ve sonra daha düşük hızları da dene. Eğer 1 MHz de dahi çalışıyorsa orada bırak ayarı :)
 
BOD = brown out detection. Voltaj fazla düşerse işlemci, saçmalayacağına, kendini pasif duruma getirir. Varsayılan ayar neyse orada bırak, sende voltaj düşmeyecek.

ATTiny işlemciyi ben de ayrıntısıyla bilmiyorum, ama "9.6 MHz internal osc" deyince harici kristale gerek olmaz herhalde. İşi görecek en düşük frekansı seçmek lazım. Frekans yükselmesi demek daha fazla parazit demek. Senin devrenin butonlara debounce yapması lazım, bu da kısa zamanda 4 tane butonu sürekli takip etmek demek. O yüzden çok da düşürmek istemiyoruz. Sen 9.6 MHz ile başla ve sonra daha düşük hızları da dene. Eğer 1 MHz de dahi çalışıyorsa orada bırak ayarı :)
kafamın bastığı kadarıyla şöyle yaptım. Bakalım çalışacak mı. :D

C:
#include <limits.h>
#define role 0
#define dk15 4

unsigned long simdikiZaman;
unsigned long oncekiZaman = 0;
const int zaman15 = 0; //900,000 15dk
void setup() {
  pinMode(dk15, INPUT);
  pinMode(role, OUTPUT);

  digitalWrite(role, LOW);

}

void loop() {
  if (digitalRead(dk15))
  {
    digitalWrite(role, HIGH);
  }
simdikiZaman = millis();
  zaman15 = zaman_farki(simdikiZaman, oncekiZaman);
  if (zaman15 >= 5000)
  {
    digitalWrite(role, LOW);
  }
}

unsigned long zaman_farki(unsigned long t1, unsigned long t2)
{
  if (t2 >= t1)
  {
    return t2 - t1;
  }
  else
  {
    return t2 + ULONG_MAX - t1 + 1;
  }
}
 
Abi bu limits.h kütüphanesi C nin standart kütüphanesiymiş ama arduino da yok. İndirecek bağlantı da bulamadım. :dusun2:
 
Bir de butona basılınca önceki zaman değişkenine o anki zamanı koyman lazım. Yoksa program sadece ilk çalıştırıldığında doğru çalışır.

C++:
  if (digitalRead(dk15))
  {
    digitalWrite(role, HIGH);
    oncekiZaman = millis();
  }
 
Şu değeri kullanabilirsin: 4294967295 veya 0xFFFFFFFF
Yukarıdaki iki kodu da ayrı ayrı denedim.
5000ms Yi 32 saniye sayıyor ikisi de. En azından saymaya başladı. Şimdi nasıl doğru saydıracağım konusu var.
Ben yine bir yerde hata yapıyorum ama nerde. O kadar çok kurcaladım ki artık ne yaptığımı da anlayamıyorum. :(

C:
#define role 0
#define dk15 4
boolean btn;
unsigned long simdikiZaman;
unsigned long oncekiZaman = 0;
int zaman15 = 0; //900,000 15dk
void setup() {
  pinMode(dk15, INPUT);
  pinMode(role, OUTPUT);

  digitalWrite(role, LOW);

}

void loop() {
  if (digitalRead(dk15))
  {
    digitalWrite(role, HIGH);
    oncekiZaman = millis();
  }
    simdikiZaman = millis();
    zaman15 = zaman_farki(simdikiZaman, oncekiZaman);
    if (zaman15 >= 5000)
    {
      digitalWrite(role, LOW);
    }
    
}

unsigned long zaman_farki(unsigned long t1, unsigned long t2)
{
  if (t2 >= t1)
  {
    return t2 - t1;
  }
  else
  {
    return t2 + 0xFFFFFFFF - t1 + 1;
  }
}
 
Bir kere zaman farkı fonksiyonunu kullanıldığı yerin üstüne koy. Şu anda neden bu konuda derleyici uyarı vermiyor bilmiyorum ama fonksiyonun kullanılmadan önce tanımlı olması önemli.

Bir de zaman15 değişkenini de unsigned long yap. Şu anda int. 65 saniyeye kadar sorun çıkmaz ama sonrasında gene bekleme süresi yanlış olur.

İstenen bekleme zamanı ile gerçek bekleme zamanı orantılı oluyorsa, mesela 5000 istiyorsun 32000 çıkıyor, 7500 istiyorsun 48000 çıkıyor gibi, o zaman sorun saat hızı ile ilgilidir.
 
Bir kere zaman farkı fonksiyonunu kullanıldığı yerin üstüne koy. Şu anda neden bu konuda derleyici uyarı vermiyor bilmiyorum ama fonksiyonun kullanılmadan önce tanımlı olması önemli.

Bir de zaman15 değişkenini de unsigned long yap. Şu anda int. 65 saniyeye kadar sorun çıkmaz ama sonrasında gene bekleme süresi yanlış olur.
Bu iki adımı yapınca bas bırak buton oldu. Basınca yanıyor, bırakınca sönüyor.
C:
#define role 0
#define dk15 4
boolean btn;
unsigned long simdikiZaman;
unsigned long oncekiZaman = 0;
unsigned long zaman15 = 0; //900,000 15dk
void setup() {
  pinMode(dk15, INPUT);
  pinMode(role, OUTPUT);

  digitalWrite(role, LOW);

}

unsigned long zaman_farki(unsigned long t1, unsigned long t2)
{
  if (t2 >= t1)
  {
    return t2 - t1;
  }
  else
  {
    return t2 + 0xFFFFFFFF - t1 + 1;
  }
}

void loop() {
  if (digitalRead(dk15))
  {
    digitalWrite(role, HIGH);
    oncekiZaman = millis();
  }
    simdikiZaman = millis();
    zaman15 = zaman_farki(simdikiZaman, oncekiZaman);
    if (zaman15 >= 5000)
    {
      digitalWrite(role, LOW);
    }
    
}
 

Çevrimiçi personel

Forum istatistikleri

Konular
5,854
Mesajlar
99,805
Üyeler
2,482
Son üye
ilker29

Son kaynaklar

Son profil mesajları

gruptaki arkadaşlara selamlar. sıteyi bu gün fark ettim. Asansör için 2x7 segment LCD gösterge üretmek istiyorum. acaba bu sayfadaki arkadaşlardan destek alabilirmiyim. LCD nin mantık açılımı ektedir.
deneyci wrote on TA3UIS's profile.
Selam.
Amatör telsiz lisansı nasıl alınıyor?
Lisansı olmayanı forumlarına almıyorlar. :)
Bilgi alamıyoruz.
cemalettin keçeci wrote on HaydarBaris's profile.
barış kardeşim bende bu sene akıllı denizaltı projesine girdim ve sensörleri arastırıyorum tam olarak hangi sensör ve markaları kullandınız yardımcı olabilir misin?
m.white wrote on Altair's profile.
İyi akşamlar.Arabanız ne marka ve sorunu nedir.Ben araba tamircisi değilim ama tamirden anlarım.
* En mühim ve feyizli vazifelerimiz millî eğitim işleridir. Millî eğitim işlerinde mutlaka muzaffer olmak lâzımdır. Bir milletin hakikî kurtuluşu ancak bu suretle olur. (1922)
Back
Top