Arduino ile karedalgayı bit lere nasıl ceviririm

  • Konbuyu başlatan Konbuyu başlatan WattMan
  • Başlangıç tarihi Başlangıç tarihi

WattMan

Üye
Katılım
26 Eki 2019
Mesajlar
246
Puanları
1
Yaş
47
Merhaba , Arduino pin2 girişine uygulanan karedalganın açık kalma sürelerini ve kapalı kalma sürelerini ölçerek bunları bitlere çevirmek istiyorum ?
38khz taşıyıcı sinyalimi anahtarlı yorum yani 38khz yi 10ms aktif 5ms kapalı 15ms aktif ediyorum ve bunu tssp4038 veriyorum çıkışı başka bir Arduino pin2 ye giriyorum çeşitli kodlar demedim fakat süreleri yanlış okuyor ve işlem yapamıyorum

tssp4038 38khz sinyal gelince çıkış Low oluyor bende bu 38khz açıp kapatarak karedalgayi olustuyorum.

Bu koduna yardıma ihtiyacım var tsop4038 den gelen hight low bilgilerini bitlere donusturmek istiyorum

15ms hight ise 1 bit
5ms low ise bekleme
10ms hight ise 0 bit

​

 
TSSP4038 v.b ile işlem yaparken sürelerin yanlış okunmasının sebebi fonksiyonunun bloklayıcı yapısından kaynaklanıyordur.
Örnek: pulseIn() bir sinyalin başlamasını bekler, ölçer ve bittiğinde geri döner ama bu sırada geçen diğer sinyal değişimleri aradan sıvışabilir.

TSSP4038 ile doğru süre ölçümü için interrupts kullanmak bence daha doğru sonuç verir.
TSSP4038, 38kHz sinyal varken LOW, yokken HIGH çıkış verdiğine göre, Pin 2 (Interrupt 0) ile sinyal değişimlerini yakalayıp süreleri ölçtükten sonra bitlere dönüştürülebilir.
Bu şekilde her sinyal değişiminde zaman kaydedilip daha hassas doğru sonuçlar alınabilir.

Örnek kodlar:
C++:
volatile unsigned long sonZaman = 0;
volatile unsigned long gecenSure = 0;
volatile bool sinyalDegisti = false;
volatile int sonDurum = HIGH;

void setup() {
  Serial.begin(115200);
  pinMode(2, INPUT_PULLUP); // TSSP4038 den gelen sinyal girişi
 
  // Pin 2'deki her değişimde sinyalOlc fonksiyonunu çağırırr
  attachInterrupt(digitalPinToInterrupt(2), sinyalOlc, CHANGE);
 
  Serial.println("Sinyal bekleniyor.");
}

void loop() {

  if (sinyalDegisti) {
    unsigned long milisaniyeSuresi = gecenSure / 1000;
    int durum = sonDurum;
    sinyalDegisti = false;

    /*
     TSSP4038 çalışması:
     38kHz Sinyal VARSA = Pin LOW olur (0V)
     38kHz Sinyal YOKSA = Pin HIGH olur (5V)
     */

    if (durum == LOW) {

  
      if (milisaniyeSuresi >= 9 && milisaniyeSuresi <= 11) {
        Serial.println("Sonuç: 0 biti (10ms Sinyal)");
      }
      else if (milisaniyeSuresi >= 14 && milisaniyeSuresi <= 16) {
        Serial.println("Sonuç: 1 biti(15ms Sinyal)");
      }
    }
    else {

  
      if (milisaniyeSuresi >= 4 && milisaniyeSuresi <= 6) {
        Serial.println("Durum: bekleme (5ms Boşluk)");
      }
    }
  }
}


void sinyalOlc() {
  unsigned long suAnkiZaman = micros();
  gecenSure = suAnkiZaman - sonZaman;
  sonZaman = suAnkiZaman;
  sonDurum = digitalRead(2);
  sinyalDegisti = true;
}
 
Eğer anahtarlama yapacaksan yani bir bir bitlik veri değişimi istiyorsan yukarıdaki kod işini görecektir ama bitlerden oluşan bir veri taşıyacaksan yukarıdaki gibi bir yöntem kullanamazsın çünkü arduino kitaplığındaki fonksiyonlar üst seviye kullanıcı dostu fonksiyonlardır ve zaman kaybına sebep olur. veri taşırken kullanamazsın. Eğer kızılötesi bir iletişimle veri taşıyacaksan Arduino için IRremote kitaplığı var hem veri alıp hem veri gönderebilirsin.

https://github.com/Arduino-IRremote/Arduino-IRremote
 
Eğer anahtarlama yapacaksan yani bir bir bitlik veri değişimi istiyorsan yukarıdaki kod işini görecektir ama bitlerden oluşan bir veri taşıyacaksan yukarıdaki gibi bir yöntem kullanamazsın çünkü arduino kitaplığındaki fonksiyonlar üst seviye kullanıcı dostu fonksiyonlardır ve zaman kaybına sebep olur. veri taşırken kullanamazsın. Eğer kızılötesi bir iletişimle veri taşıyacaksan Arduino için IRremote kitaplığı var hem veri alıp hem veri gönderebilirsin.

https://github.com/Arduino-IRremote/Arduino-IRremote
Evet yukarıda kod ile bitleri alabiliyorum ama metin olarak çevirirken bazen istedigim karakter çıkıyor sonra komple gelen veri bozuluyor, şimdi irremote kutuphanesini denedim ve istedigim yazıyı aktarabiliyorum, ben mantığını öğrenmek ve yapabilmek için bastaki gibi bit bit aktarmak istedim, ama 2 gündür uğraşıyorum olmuyor. IR remote ile 5dk de oldu
 
IRremote kütüphanesinin 5 dakikada çalışması normal, çünkü o kütüphane arka planda gürültü filtreleme, sinyal toleransı ve protokol senkronizasyonu vb gibi senin manuel yapmaya çalıştığın karmaşık işleri halletmeye çalışıyor.

Bence manuel yönteminde verinin bir süre sonra bozulmasının en büyük sebebi senkronizasyon kayması. Eğer bir biti bile kaçırırsan veya hatalı okursan, sonraki tüm bitler bir yana kayar ve 01000001 A olması gereken veri karakter değiştirir.


Mantığı kavramak için basit kod yapısı ile gelen bitleri 8 li gruplar halinde birleştirip karaktere dönüştür.

C++:
volatile unsigned long gecenSure = 0;
volatile unsigned long sonZaman = 0;
volatile bool yeniVeri = false;

byte gelenBayt = 0;   //Bitleri burada taplar
int bitSayaci = 0;    //8 bit olunca yazdırırr

void setup() {
  Serial.begin(115200);
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), sinyalOlc, CHANGE);
}

void loop() {
  if (yeniVeri) {
    unsigned long sure = gecenSure / 1000;
    int durum = digitalRead(2); //Sinyal bittikten sonraki durum (HIGH ise sinyal az önce LOW du)
    yeniVeri = false;

    //sinyal VARKEN TSSP çıkışı LOW iken geçen süreyi ölçer
    if (durum == HIGH) {
 
      int okunanBit = -1;
 
      if (sure >= 9 && sure <= 11) okunanBit = 0;       // 10ms  0 Biti
      else if (sure >= 14 && sure <= 16) okunanBit = 1; // 15ms  1 Biti
      else if (sure > 25) {    // 30ms gibi uzun bir sinyal gelirse diye
        bitSayaci = 0; gelenBayt = 0;            
        return;
      }

      if (okunanBit != -1) {

        gelenBayt |= (okunanBit << bitSayaci);
        bitSayaci++;

        if (bitSayaci == 8) {
          Serial.print((char)gelenBayt);
          bitSayaci = 0;
          gelenBayt = 0;
        }
      }
    }
  }
}

void sinyalOlc() {
  unsigned long suAn = micros();
  gecenSure = suAn - sonZaman;
  sonZaman = suAn;
  yeniVeri = true;
}


Verici tarafında mantıken sıralaması şöyle olmalı:

1- 30ms sinyal ver. Başlangıç
2 -10ms Bekle (Boşluk)
3 - Karakterin 8 bitini sırayla gönder Örn: Her bit için 10ms veya 15ms sinyal, aralarda 5ms boşluk
 
Son düzenleme:
Yani alıcı ve verici tarafını kütüphanesiz baştan özetlersek mantık olarak şöyle bir kod yapısı olabilir sanırım.

Verici tarafı:

C++:
const int irLedPin = 3;//IR LED bu pine bağlı

void setup() {
  pinMode(irLedPin, OUTPUT);
}

void sinyalGonder(int msSure) {
  tone(irLedPin, 38000);
  delay(msSure);
  noTone(irLedPin);
}

void harfGonder(char karakter) {
  // HEADER - 30ms sinyal ve 10ms boşluk
  sinyalGonder(30);
  delay(10);

  for (int i = 0; i < 8; i++) {
    bool bitDegeri = bitRead(karakter, i);
 
    if (bitDegeri == 0) sinyalGonder(10);
    else sinyalGonder(15);
 
    delay(5); //Her bit arası 5ms bekle
  }
}

void loop() {
  harfGonder('A');
  delay(2000);
}





Alıcı tarafı:
C++:
// Değişkenlerimiz (Kütüphanesiz)
volatile unsigned long gecenSure = 0;
volatile unsigned long sonZaman = 0;
volatile bool yeniVeri = false;
byte gelenBayt = 0;
int bitSayaci = 0;
bool veriBasladi = false;

void setup() {
  Serial.begin(115200);
  pinMode(2, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(2), sinyalOlc, CHANGE);
}

void loop() {
  if (yeniVeri) {
    unsigned long sure = gecenSure / 1000;
    int durum = digitalRead(2);
    yeniVeri = false;


    if (durum == HIGH) {
 
     //1. HEADER (BAŞLANGIÇ) KONTROLÜ
 if (sure >= 28 && sure <= 32) {  // 30ms mi ortalama?
        veriBasladi = true;
        bitSayaci = 0;
        gelenBayt = 0;
        Serial.println("\n Yeni Paket Basladi ");
      }

      else if (veriBasladi) {
        if (sure >= 9 && sure <= 11) {
          bitWrite(gelenBayt, bitSayaci, 0);
          bitSayaci++;
        }
        else if (sure >= 14 && sure <= 16) {
          bitWrite(gelenBayt, bitSayaci, 1);
          bitSayaci++;
        }


        if (bitSayaci == 8) {
          Serial.print("Okunan Karaktert: ");
          Serial.println((char)gelenBayt);
          veriBasladi = false;
        }
      }
    }
  }
}


void sinyalOlc() {
  unsigned long suAn = micros();
  gecenSure = suAn - sonZaman;
  sonZaman = suAn;
  yeniVeri = true;
}
 
Son düzenleme:
Yani alıcı ve verici tarafını kütüphanesiz baştan özetlersek mantık olarak şöyle bir kod yapısı olabilir sanırım.

Verici tarafı:

C++:
const int irLedPin = 3;//IR LED bu pine bağlı

void setup() {
  pinMode(irLedPin, OUTPUT);
}

void sinyalGonder(int msSure) {
  tone(irLedPin, 38000);
  delay(msSure);
  noTone(irLedPin);
}

void harfGonder(char karakter) {
  // HEADER - 30ms sinyal ve 10ms boşluk
  sinyalGonder(30);
  delay(10);

  for (int i = 0; i < 8; i++) {
    bool bitDegeri = bitRead(karakter, i);
 
    if (bitDegeri == 0) sinyalGonder(10);
    else sinyalGonder(15);
 
    delay(5); //Her bit arası 5ms bekle
  }
}

void loop() {
  harfGonder('A');
  delay(2000);
}





Alıcı tarafı:
C++:
// Değişkenlerimiz (Kütüphanesiz)
volatile unsigned long gecenSure = 0;
volatile unsigned long sonZaman = 0;
volatile bool yeniVeri = false;
byte gelenBayt = 0;
int bitSayaci = 0;
bool veriBasladi = false;

void setup() {
  Serial.begin(115200);
  pinMode(2, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(2), sinyalOlc, CHANGE);
}

void loop() {
  if (yeniVeri) {
    unsigned long sure = gecenSure / 1000;
    int durum = digitalRead(2);
    yeniVeri = false;


    if (durum == HIGH) {
 
     //1. HEADER (BAŞLANGIÇ) KONTROLÜ
 if (sure >= 28 && sure <= 32) {  // 30ms mi ortalama?
        veriBasladi = true;
        bitSayaci = 0;
        gelenBayt = 0;
        Serial.println("\n Yeni Paket Basladi ");
      }

      else if (veriBasladi) {
        if (sure >= 9 && sure <= 11) {
          bitWrite(gelenBayt, bitSayaci, 0);
          bitSayaci++;
        }
        else if (sure >= 14 && sure <= 16) {
          bitWrite(gelenBayt, bitSayaci, 1);
          bitSayaci++;
        }


        if (bitSayaci == 8) {
          Serial.print("Okunan Karaktert: ");
          Serial.println((char)gelenBayt);
          veriBasladi = false;
        }
      }
    }
  }
}


void sinyalOlc() {
  unsigned long suAn = micros();
  gecenSure = suAn - sonZaman;
  sonZaman = suAn;
  yeniVeri = true;
}
Efendim teşekkür ederim , kütüphanesiz başarılı şekilde yaptım, şuanda geliştirme amaçlı neler yapabilirim bunu düşünüyorum desteğiniz olmasa basaramazdim
 

Ekli dosyalar

  • 17727490486972321175014199265745.webp
    17727490486972321175014199265745.webp
    77.8 KB · Görüntüleme: 5
Üstteki alıcı ve verici yapılarda mantığı kavrama adına genel kod yapılarını paylaşmıştım.
Aklıma gelen yapılabilecek bazı geliştirmeleri araştırıp deneyebilirsiniz.

Hata kontrolü
Şu anki yapıda havadan gelen bir gürültü bir biti değiştirirse, A harfi yerine Q harfi okursun ve alıcı bunun yanlış olduğunu anlamaz.

Veri paketleme
Sadece tek harf değil, sensör verileri veya komutlar göndermek istiyorsanız bir paket yapısı yapısı oluşturulabilir.

Hız optimizasyonu- süreleri kısaltma
Şu an ki kod yapısı 10ms-15ms gibi çok uzun süreler kullanıyor. TSSP4038 daha hızlı tepki verecek şekilde düzenlenebilir.

Metin tamamlama
Harfleri tek tek ekrana basmak yerine, bir cümleyi tamamlayıp topluca basılabilir.

Karşılıklı konuşma
Şu an verici körlemesine gönderiyor, alıcının alıp almadığını bilmiyor.
 

Forum istatistikleri

Konular
133,403
Mesajlar
971,234
Kullanıcılar
459,327
Son üye
108976

Yeni konular

Çevrimiçi üyeler

Geri
Üst