20 Mart 2019, 23:33:16

Haberler:

Forum kuralları güncellendi LÜTFEN  okuyunuz:  https://bit.ly/2IjR3ME


İki Arduino arasında 16 bit veri gönderimi

Başlatan cirak05, 23 Aralık 2018, 16:39:57

cirak05

23 Aralık 2018, 16:39:57 Son düzenlenme: 23 Aralık 2018, 16:40:59 ekucuk
Merhaba

İki arduino arasında seri haberleşme ile 1 baytlık veri gönderimi yapabiliyorum ama 2 baytlık transferin nasıl yapılacağını bulamadım, mümkün müdür yoksa ben mi ulaşamadım bu bilgiye?

Yazdığım kodda gelen veriyi 0-99 veya 100-255 aralığa göre hafızaya kaydediyorum. Ama daha yüksek veri değeri göndermem ve almam lazım, 2 bayt gibi

Örneğin; ilk hafızaya alacağım değer 0 - 2000, diğeri 2001-15000 gibi...

Teşekkürler.

Şuan alıcıda kullandığım kodlar:

Kod Seç
  if (Serial.available() > 0

{
    
byte GELENVERI Serial.read();

    if (
GELENVERI && GELENVERI 99) {
      
EEPROM.write(0GELENVERI);
    }

    if (
100 GELENVERI && GELENVERI 255) {
      
EEPROM.write(10GELENVERI);
    }
}

erkantr67

"Nasıl gönderirim?"sorusuna karşılık bize yardımcı olmak için alıcı kodu mu veriyorsun?

Kod Seç
Function tek_gonderim(int gonderilecek)
{
  
//Tek bayt gönderdiğin kod.
  //Not: Tek bayt gönderdiğin kodun değişken parametresine "gonderilecek" yaz.



For(
j=0;j<2;j++)
{
    
tek_gonderim(deger[j]);
}


Kabil ATICI

23 Aralık 2018, 19:17:32 #2 Son düzenlenme: 23 Aralık 2018, 20:09:43 Kabil ATICI
http://subethasoftware.com/2014/12/16/splitting-a-16-bit-value-to-two-8-bit-values-in-c/
yukarıdaki link üzerinde anlatıldığı gibi
öncelikle kodunu 2 adet 8 bitlik  veriye dönüştür.
uint8_t  bytes[2];
uint16_t value;
 
value = 0x1234; //(bu aynı zamanda senin göndereceğin değer)
 
bytes[0] = value >> 8;     // high byte (0x12)
bytes[1] = value & 0x00FF; // low byte (0x34)

baytları ayrı ayrı gönder
 aldığın zamanda
value=bytes[0];
value=value<<8;
value |=bytes[1];


örneğin...
 if (0 < value && value< 350) {
    EEPROM.write(0, value);
    }

http://projectsfromtech.blogspot.com/2013/09/combine-2-bytes-into-int-on-arduino.html
değişik yöntemler de var.
ambar7

cirak05

23 Aralık 2018, 19:26:05 #3 Son düzenlenme: 23 Aralık 2018, 19:30:44 ekucuk
Alıntı yapılan: erkantr67 - 23 Aralık 2018, 19:03:11"Nasıl gönderirim?"sorusuna karşılık bize yardımcı olmak için alıcı kodu mu veriyorsun?

Kod Seç
Function tek_gonderim(int gonderilecek)
{
  
//Tek bayt gönderdiğin kod.
  //Not: Tek bayt gönderdiğin kodun değişken parametresine "gonderilecek" yaz.



For(
j=0;j<2;j++)
{
    
tek_gonderim(deger[j]);
}



Cevapladığınız için teşekkür ederim, hocam arduino da yeniyim ya ben eksik anlattım veya sizin yazdığınız kodun inceliğini anlamadım.

Alıcı kodunu verme amacım; kabaca yapmak istediğim düzeni anlatmak içindi, verici düzeneği basit zaten, 8 bitlik bilgiyi gönderiyor ve alıcı arduino ya kaydediyorum. Benim sorunum 16 bitlik (2 baytlık) veriyi gönderim ve almak ile ilgili, sizin yazdığınız kod bununla ilgili ise özür dilerim tam anlayamadım.

Gönderici Arduino da butonlara tanımlı değerler var, butona basıldığında bilgi gidiyor.

Örneğin; verici arduino dan 55 değerini gönderiyorum, alıcı arduino da bunu görüp kaydediyorum ama 255 sonra yani 8 bitten fazlasını nasıl yaparım bilmiyorum.

VERİCİ:

Kod Seç
int DEGER 55;
if (
digitalRead(buton1) == LOW) {      
    
Serial.write(DEGER);
}



ALICI:

Kod Seç
  if (Serial.available() > 0) {
    
int DEGER Serial.read();
    if (
DEGER && DEGER99) {
    
EEPROM.write(0DEGER);
    }
}

erkantr67

@Kabil ATICI açıkça anlatmış.

GÖNDERİCİ:
Kod Seç
unsigned int16 DEGER 12345// 16 bitlik değişken oluşturduk. 
unsigned int8  on_bellek[2]={0};

if (
digitalRead(buton1) == LOW) {    
    
    
on_bellek[0] = DEGER 0x00FF// DEGER 16 bitlik değişkeninin ilk 8 bitini on_bellek'e yükledik.
    
on_bellek[1] = DEGER >> 8// DEGER 16 bitlik değişkeninin 8 defa sağa kaydırıp on_bellek'e yükledik.

    
Serial.write(on_bellek,2); // Serial.write(buf, len)  böyle bir kullanım varmış.
 
}

ALICI:

Kod Seç
  

int i
=0;
UNSIGNED INT16 DEGER=0;
UNSIGNED INT8 TAMPON[2]={0};

if (
Serial.available() > 0
{
    for(
i=0;i<2;i++)
    {
      
TAMPON[i] = Serial.read();
    }
    
DEGER=0;
    
DEGER  TAMPON[1];  // Yüksek değerli veri "DEGER" 16 bitlik değişkenine yüklendi.
    
DEGER  DEGER << 8// "DEGER" 16 bitlik değişkeni 8 defa sola kaydırıldı ve kendisine yüklendi.
    
DEGER |= TAMPON[0];  // Düşük değerli(ilk gelen) veri, "DEGER" 16 bitlik değişkeni ile "veya" işlemine tabi tutuldu.
 

// Sonrası sana kalmış. 
    
if (DEGER && DEGER99
    {
      
EEPROM.write(0DEGER);
    }
}

cirak05

Herkese hayırlı günler, yardımlarınız için teşekkürler.

Sizlerin verdiği örneklerde veri gönderimi "ARRAY" dizi şeklinde diye tarif ediliyor, yanılmıyorsam.

Bir de şöyle birşey denedim. Siz ne dersiniz, daha iyi mi yoksa sıkıntılara yol açar mı ileride, denemesini yaptım çalıştı aslında ama fikrinizi almak istedim.

Teşekkürler.


Kod Seç
// VERICI:

int DEGER 65535;

if (
digitalRead(BUTON) == LOW) {
  while (
digitalRead(BUTON) == LOW);

  
int LOBY lowByte(DEGER);
  
int HIBY highByte(DEGER);

  
EEPROM.write(0LOBY);
  
EEPROM.write(1HIBY);

  
Serial.write(HIBY);
  
delay(5);
  
Serial.write(LOBY);
  
delay(5);
  
Serial.write(1);
  
delay(5);
}[ / 
code]

[
code]
// ALICI:

int ALANKODU;

if (
Serial.available() > 0) {

  
delay(50);

  
int HIBY Serial.read();
  
delay(5);
  
int LOBY Serial.read();
  
delay(5);
  
ALANKODU Serial.read();
  
delay(5);


  if (
ALANKODU == 1) {
    
EEPROM.write(0LOBY);
    
EEPROM.write(1HIBY);
  }

  if (
ALANKODU == 2) {
    
EEPROM.write(2LOBY);
    
EEPROM.write(3HIBY);
  }
}
[ / 
code]

erkantr67

Gecikme koymamalısın! Alıcı ve verici sistemler birbirinden bağımsız.

Gelen veri boyutu küçük olduğunda neyse de eğer uart tamponunu taşıracak veri alımı yaparsan ileride aynı alım protokolü ile gelen verileri kaçırırsın.

Alıcıyı gelen veriyi gelir gelmez bellekleyecek şekilde düzenlemen iyi olur.


Ve gelen veri bayrağını kontrol eden blok içerisinde sadece bellekleme kodları yer alsın. Hatta veri alımını kesmeyle yapmalısın. Eeprom'a yazma  işlemi uart tampodaki bütün veriler ram belleğe yazıldıktan sonra yapılmalı. Böyle sıkıntı olur. Verileri kesmeyle al, ortalık sakinledikten sonra nereye yazarsan yaz.

Şuanki alım şekli uçurumdan aşağı paldur küldür, takla ata ata inen araba gibi.

cirak05

29 Aralık 2018, 18:16:35 #7 Son düzenlenme: 29 Aralık 2018, 18:21:45 ekucuk
Hocam gecikmeleri çıkardım, sadece alıcıda 50ms gecikme koydum, 3 veri bilgisinin gelişini tamamlayacak şekilde.

Gönderilen veri boyutu en fazla "30000" verisini geçmeyecek şekilde ayarlandı. Alıcıda kesme fonksiyonu yazdım, burada tüm kodları yazmadım, kalabalık görüntü oluşmasın diye, seri porttan veri geldiğinde kesmeye gidip yukarıda yazdığım alıcı kodunu işleyecek.

Alıntı yapılan: undefinedVe gelen veri bayrağını kontrol eden blok içerisinde sadece bellekleme kodları yer alsın.

Hocam bu dediğinizi tam anlayamadım.

Alıntı yapılan: undefinedEeprom'a yazma  işlemi uart tampodaki bütün veriler ram belleğe yazıldıktan sonra yapılmalı.

Ben alıcı kodlarında delay(50) vermemdeki amacım buydu zaten, 3 veride gelsin ve RAM'e kaydedilsin, 50 milisaniye beklesin ve gönderim sırasına göre değişkenlere atansın diye düşündüm ve bu işlemleri seri porttan bilgi geldiği anda kesmeye giderek "kesme fonksiyonu" içerisinde yapacağım. Burada eksik yada yanlış bir uygulama mı yapmış oldum.

Kod Seç
//=======================================
// ALICI:
//=======================================

void seri_kontrol() {

if (
Serial.available() > 0) {

  
delay(50);                                        // VERİLERİN TAMAMININ GELMESİNİ BEKLİYORUZ

  
int HIBY Serial.read();                        // GÖNDERİLEN İLK VERİ HIGHBYTE İDİ
  
int LOBY Serial.read();                        // GÖNDERİLEN İKİNCİ VERİ LOWBYTE İDİ
  
int ALANKODU Serial.read();                        // GÖNDERİLEN SON VERİ HANGİ BÖLÜME KAYDEDİLECEĞİ İLE İLGİLİ VERİ

  // ALAN KODUNDAKİ VERİYE GÖRE 1. VEYA 2. BÖLÜMDEKİ EEPROM ALANLARINA KAYDEDİLECEK

  
if (ALANKODU == 1) {
    
EEPROM.write(0LOBY);
    
EEPROM.write(1HIBY);
  }

  if (
ALANKODU == 2) {
    
EEPROM.write(2LOBY);
    
EEPROM.write(3HIBY);
  }
}
}

Kod Seç
//=======================================
// VERİCİ:
//=======================================

if (digitalRead(BIRINCI_BUTON) == LOW) {            // BİRİNCİ BUTONA BASINCA 25212 VERİSİ GİDECEK
  
while (digitalRead(BIRINCI_BUTON) == LOW);

  
int DEGER 25212;

  
int LOBY lowByte(DEGER);
  
int HIBY highByte(DEGER);

  
EEPROM.write(0LOBY);
  
EEPROM.write(1HIBY);

  
Serial.write(HIBY);
  
Serial.write(LOBY);
  
Serial.write(1);
}

if (
digitalRead(IKINCI_BUTON) == LOW) {            // İKİNCİ BUTONA BASINCA 10812 VERİSİ GİDECEK
  
while (digitalRead(IKINCI_BUTON) == LOW);

  
int DEGER 10812;

  
int LOBY lowByte(DEGER);
  
int HIBY highByte(DEGER);

  
EEPROM.write(0LOBY);
  
EEPROM.write(1HIBY);

  
Serial.write(HIBY);
  
Serial.write(LOBY);
  
Serial.write(2);
}

Alıntı yapılan: undefinedŞuanki alım şekli uçurumdan aşağı paldur küldür, takla ata ata inen araba gibi.

Yada en başta @Kabil ATICI ve sizin dediğiniz gibi "DİZİ" şeklindeki kodlamaya mı döneyim?

Saygılar

erkantr67

Oradaki 50ms'yi koymana gerek yok, zaten veri geldikten sonra donanım otomatik olarak "Serial.available() > 0" deyimini "true" yapar. Sizin sadece byte byte çekmeniz gerekir veriyi.

Kod Seç
//=======================================
// ALICI:
//=======================================

void seri_kontrol() {

if (
Serial.available() > 0)
{

  
//delay(50);    // gerek yok.

  
int HIBY Serial.read();                        // GÖNDERİLEN İLK VERİ HIGHBYTE İDİ
  
int LOBY Serial.read();                        // GÖNDERİLEN İKİNCİ VERİ LOWBYTE İDİ
  
int ALANKODU Serial.read();                        // GÖNDERİLEN SON VERİ HANGİ BÖLÜME KAYDEDİLECEĞİ İLE İLGİLİ VERİ

  
islem=1;
 }
}

Alıntı yapılan: undefinedVe gelen veri bayrağını kontrol eden blok içerisinde sadece bellekleme kodları yer alsın.
Kastım şu; eeprom'a yazma işlemi uzun süren bir işlem. Eğer siz eeprom'a yazma işlemini kesme bloğu içerisinde yaparsanız bir sonraki gelecek bilgi paketini kaçırabilirsiniz. Bu yüzden kesme bloğu içerisinde yeni veri geldiğine dair bir değişkeni uyarırsanız, kesme bloğu içerisinden çıktıktan sonra uyarılan değişkeni ana döngüde kontrol ederek(kontrol edip eeprom'a yazma işlemi) yeni gelebilecek olan bilgi paketinin önünü kesmiş olmazsınız. Tabi bu uyarılacak değişkeni global olarak tanımlamanız gerekli. 


Kod Seç

void seri_kontrol
() {

if (
Serial.available() > 0)
{

  
//delay(50);    // Gerek yok.
  // Bu uygulamanız için aşağıdaki yazdığınız komutlar sorun olmaz.
  // Ama 5 ve üstü gelecek olan veri paketleri için bu şekilde verileri ram belleğe çekmek 
  // gereksiz hafıza harcamanıza neden olur. Aynı işlemi dizi(array) kullanarak yapabilirsiniz. 
  
  
int HIBY Serial.read();                        
  
int LOBY Serial.read();                        
  
int ALANKODU Serial.read();                 

  
islem=1;
 }
}

Main()
{
  for(;;)
  {
    if(
islem==1)
    {
      
islem=0;
        
// ALAN KODUNDAKİ VERİYE GÖRE 1. VEYA 2. BÖLÜMDEKİ EEPROM ALANLARINA KAYDEDİLECEK

      
if (ALANKODU == 1
      {
        
EEPROM.write(0LOBY);
        
EEPROM.write(1HIBY);
      }

      if (
ALANKODU == 2
      {
        
EEPROM.write(2LOBY);
        
EEPROM.write(3HIBY);
      }
    }
  }

}

mehmet

Seri bilgiden gelen ilk byte
hangisi olduğunu anlayabilmek
için en az iki karakter boş
bilgi yollamanız da gerekli
bence.
nothing