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

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

cirak05

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:

  if (Serial.available() > 0) 

{
    byte GELENVERI = Serial.read();

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

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

ziyaretci

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

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

#2
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

#3
Alıntı yapılan: erkantr67 - 23 Aralık 2018, 16:03:11"Nasıl gönderirim?"sorusuna karşılık bize yardımcı olmak için alıcı kodu mu veriyorsun?

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İ:

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



ALICI:

  if (Serial.available() > 0) {
    int DEGER = Serial.read();
    if (0 < DEGER && DEGER< 99) {
    EEPROM.write(0, DEGER);
    }
}

ziyaretci

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

GÖNDERİCİ:
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:

  

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 (0 < DEGER && DEGER< 99) 
    {
      EEPROM.write(0, DEGER);
    }
}

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.


// VERICI:

int DEGER = 65535;

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

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

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

  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(0, LOBY);
    EEPROM.write(1, HIBY);
  }

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

ziyaretci

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

#7
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.

//=======================================
// 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(0, LOBY);
    EEPROM.write(1, HIBY);
  }

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

//=======================================
// 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(0, LOBY);
  EEPROM.write(1, HIBY);

  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(0, LOBY);
  EEPROM.write(1, HIBY);

  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

ziyaretci

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.

//=======================================
// 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. 


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(0, LOBY);
        EEPROM.write(1, HIBY);
      }

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

}

mehmet

Seri bilgiden gelen ilk byte
hangisi olduğunu anlayabilmek
için en az iki karakter boş
bilgi yollamanız da gerekli
bence.
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr

interrupter

Mrb arkadasla aradan uzun zaman geçmiş ama yeniden konu açmak istemedim.
Problemim şu Slav arduinodan bir 16 bitlik değişkeni master arduino ya göndermek istiyorum ancak o kadar ugrasmama rağmen yapamadim ve en son aklıma şöyle bir durum geldi

16 bitlik değişkenin Max 3000 değerini alıyor.

 Ben bu değeri sabit bir değerle bölerek 255 in altında karşıya göndersem ve karşı tarafta da gelen veriyi yine aynı sabit sayı ile çarparak asıl sayıya ulassam sorun yaratır mı, bölme işlemi float olacak ve fload değer serial den gönderilecek

z

Soyle yap.

Gondermek istedigin sayi x


H = x/128
L = X - (H*128)

H = H OR 128

Simdi H ve L yi yolla.

Pespese aldigin 2 byte veriden

8. biti 1 olan H
8. biti 0 olan da L dir.

X sayisini geri elde edebilmek icin X=(H and 127)*128 + L

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

kimlenbu

Eğer ekleyeceğin ekstra bytelar sıkıntı olmazsa

NMEA 0183 benzeri bir yapı kullanabilirsin.

Örnek :

$AYXDR,VERI1,VERI2*XX

XX kısmı checksum, verinin doğruluğunu da kontrol etmiş olursun.

interrupter

kimlenbu üstadım ("NMEA 0183") bu kısmı anlamadım.


8 bit veride sorunum yok aktarabiliyorum ancak 16 bit göndermem gerekiyor



gönderici kodlarım


button=digitalRead(buton); //butona basıldı ise seri porttan veri gönder
if (button==0)
{
high=highByte(sayac);
low=lowByte(sayac);
Serial.write(low); //8 bit bu bölümü mastera gönderip alabiliyorum
Serial.write(high); //msb kısmını çözemedim
}


alıcı kodlarım




void serialEvent() {
digitalWrite(a,LOW);
byte a=0;
if (Serial.available() > 0)
{
a= Serial.read();

box.clear(); 
box.print(a);
}
}



bu sekilde 1 byte veri aktarabiliyorum ama 2 byte lık veriyi çözemedim

mehmet

Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr