Nextion HMI ve UART DMA Receiver Senkronizasyon Problemi

Başlatan isoment01, 21 Nisan 2020, 17:51:42

isoment01

Arkadaşlar Nextion Dokunmatik Panelden 8 byte lık veri alıyorum 50ms aralıklarla ve data fram'i  şu şekilde;
[0x71, DATA, 0x00, 0x00, 0x00, 0xF,F 0xFF, 0xFF] ilk bayt ve son 3 bayt sabit gönderiliyor. Aradaki 4 bytelık veri kullanıcı için saklanıyor ben sadece 1 byte'ını kullanıyorum. Uart Dma için 8 byte lık buffer tanımladım ve RxCpltCallback fonksiyonunda gelen dataya parser uyguladım fakat burada senkronizasyon sorunum var. Normalde yukarıdaki frame'in gelmesini umuyorum fakat çoğu zaman bufferın elemanlarının yeri kayıyor böyle olunca da istediğim datayı çekemiyorum. DMA'yı başlatmadan bir if kontrol blogunda senkronizasyon bayrağı kurdum doğru frame gelene kadar polling metodu ile direk okuma yaptım  bu işe yarıyor istediğim frame geldiğinde senkronizasyon tamamlandı diye düşünüp DMA'yı hemen burada enable ettim ama DMA bufferında kaymalar oldu.  Bu sorunun nedeni neden olabilir ?

e-zeki

 receive rutini 8 byte ile tetikleniyorsa nextion 8 byttan farklı herhangi bir paket gönderdiği an senkronizasyonun kayar ve tekrar düzelmesi için nextiondan toplamda 8 Bytelık hatanın birikmesini beklersin. çünkü sen her 8 byte reception da bir çalışıyorsun. receive rutinini 1 byte yap, 8 bytelık parser yaz. O zaman düzelir.

isoment01

Alıntı yapılan: e-zeki - 21 Nisan 2020, 18:26:51receive rutini 8 byte ile tetikleniyorsa nextion 8 byttan farklı herhangi bir paket gönderdiği an senkronizasyonun kayar ve tekrar düzelmesi için nextiondan toplamda 8 Bytelık hatanın birikmesini beklersin. çünkü sen her 8 byte reception da bir çalışıyorsun. receive rutinini 1 byte yap, 8 bytelık parser yaz. O zaman düzelir.

şimdi bir şeyleri çözmeye başladım, ana döngünün üstünde bir kontrol blogu kurdum
  while(flag==RESET)
  {
	  HAL_UART_Receive(&huart2, a, 8, 10);

	  if(a[0]==0x71 && a[5]==0xFF && a[6]==0xFF && a[7]==0xFF)
	  {
		  HAL_UART_Receive_DMA(&huart2, (uint8_t*)&TouchScreenRxData, sizeof(TouchScreenRxData));
		  flag= SET;
	  }

  }
döngüde polling ile bir buffera kaydetme yaptım istediğim frame'i aldıgımda dma'yı aktif ettim dma'daki frame'de kaymalar oldugunu gördüm. Nextion hep 8 bytelık paket gönderiyor bu arada hocam. En son 1 byte lık buffera kaydet 8 byte lık parser yap dediğiniz kısmı biraz daha açar mısınız TouchScreenRxData bufferımı 1 byte a düşürdükten sonra callbackte nasıl bir kontrol blogu olusturacagım ?

Mucit23

Bu şekilde yapmak yerine şöyle bir yöntem uygulayabilirsin.

Nextionda herhangi bir event oluştuğu zaman yada sabit bir veri göndereceğin zaman göndereceğin verinin başına ve sonuna belirleyici karakterler ekle

Örneğin bir textbox verisi göndereceksen aşağıdaki gibi yapı kullan.

Textbox verisi "Merhaba" olsun. kutucuğun id'si de "t1" olsun.

*id|veri#
*t1|Merhaba#

frame başı için yıldız karakteri, frame sonu için sharp karakteri kullanılabilir. Kendinde belirleyebilirsin. Daha sonra Uart RX kesmesini aktif et. kesme fonksiyonu içinde karakter başı ve sonunu takip ederek arda gelen verileri takip etmen gerekiyor. Zor değil algoritma. Bu şekilde çok işlevsel çalışan sistemler kurabilirsin.
 

isoment01

Alıntı yapılan: Mucit23 - 21 Nisan 2020, 20:36:42Bu şekilde yapmak yerine şöyle bir yöntem uygulayabilirsin.

Nextionda herhangi bir event oluştuğu zaman yada sabit bir veri göndereceğin zaman göndereceğin verinin başına ve sonuna belirleyici karakterler ekle

Örneğin bir textbox verisi göndereceksen aşağıdaki gibi yapı kullan.

Textbox verisi "Merhaba" olsun. kutucuğun id'si de "t1" olsun.

*id|veri#
*t1|Merhaba#

frame başı için yıldız karakteri, frame sonu için sharp karakteri kullanılabilir. Kendinde belirleyebilirsin. Daha sonra Uart RX kesmesini aktif et. kesme fonksiyonu içinde karakter başı ve sonunu takip ederek arda gelen verileri takip etmen gerekiyor. Zor değil algoritma. Bu şekilde çok işlevsel çalışan sistemler kurabilirsin.
 
hocam zaten yukarda frame'in nasıl oldugunu belirttim datanın başı ve sonu belli frame şu şekilde :
0x71 DATA DATA DATA DATA 0xFF 0xFF 0xFF baştaki ilk bayt ve son üç bayt tamda dediğinizi yapıyor. Fakat sıkıntı bunların sıraları kayıyor yıldız koysam başına ben başta gelmesini beklerken ortada geliyor gibi düşünün aslında ortada gelmiyor değil ben öyle alıyorum garip bir şekilde.

isoment01

Cihazı seri arayüzde izledim dataların gelmesinde bir problem yok.
Polling yaptığımda düzgün bir şekilde parse edip alabiliyorum bunda da problem yok.
DMA'da neden sıralama kaçırıyor ?
Bir algoritma kurup bunu çalıştırarak veriyi çekebilirim fakat kök nedeni bulamadım.
Hatayı bastırmak da içime sinmiyor.

e-zeki

@Mucit23'in söylediği doğru. nextion mesaj sonuna 0xFF basıyor evet fakat senin kurduğun sistemde sadece unsigned char datalar için anlamlı olur. signed int veri gönderecek olursan frame
[0x71, DATA, 0xFF, 0xFF, 0xFF, 0xFF 0xFF, 0xFF]
gibi bir hal alır bu da gelen datayı yanlış parslamana sebep olur. Ayrıca kodda bilmeden yaptığın hatalı gönderimlerde Nextion 4 Byte'lık bir hata mesajı basar 1 byte error 3 byte 0xFF şeklinde. bu mesajlardan birisi gelirse de dma buffer'ın kayar yine düzeltemezsin.

Mucitin söylediği gibi balşangıç ve bitiş karakterlerini kendine özel hale getirirsen hata oranı sıfıra  yakın olur.
receive rutinini dediğim gibi 1 byte olarak yapar ve başlangıç byte'ı gelmeden gelen her paketi görmezden gelip başlangıç paketiyle birlikte saymaya başlarsın ve 8. karakterin senin belirlediğin bitiş karakteri olup olmadığını kontrol edersin.
 8. paket bitiş karakteri değilse yine aldıklarını siler görmezden gelirsin sayaçlarını sıfırlarsın.
bu yöntemle mesaj kaçırabilirsin fakat kayma hatası 2 mesaj döngüsünde normale çekilir.

nextionda 3 farklı proje yaptım receive rutininin 1 den büyük olduğu her durumda kayma sorunu oldu. 1 byte parser en kullanışlı çözüm bence.

Mucit23

Gelen verileri byte byte al. Dma ile paket alımında senkronizasyon sorunu olabilir ki bence karakter kaçırmanın sebebi budur. Dma kullanıyorsan bile buffer boyutunu 1 yap. DMA Tc kesmesini aktif et. Bu sayede her bir karakter geldiğinde dma kesme oluşturacak sende kesme içerisinde karakter başı sonu vs gibi kontrolleri yaparsın. Bu şekilde yaparsan senkronizasyon sorunu yaşamazsın.

isoment01

Alıntı yapılan: Mucit23 - 22 Nisan 2020, 10:34:23Gelen verileri byte byte al. Dma ile paket alımında senkronizasyon sorunu olabilir ki bence karakter kaçırmanın sebebi budur. Dma kullanıyorsan bile buffer boyutunu 1 yap. DMA Tc kesmesini aktif et. Bu sayede her bir karakter geldiğinde dma kesme oluşturacak sende kesme içerisinde karakter başı sonu vs gibi kontrolleri yaparsın. Bu şekilde yaparsan senkronizasyon sorunu yaşamazsın.
Alıntı yapılan: e-zeki - 22 Nisan 2020, 08:55:53@Mucit23'in söylediği doğru. nextion mesaj sonuna 0xFF basıyor evet fakat senin kurduğun sistemde sadece unsigned char datalar için anlamlı olur. signed int veri gönderecek olursan frame
[0x71, DATA, 0xFF, 0xFF, 0xFF, 0xFF 0xFF, 0xFF]
gibi bir hal alır bu da gelen datayı yanlış parslamana sebep olur. Ayrıca kodda bilmeden yaptığın hatalı gönderimlerde Nextion 4 Byte'lık bir hata mesajı basar 1 byte error 3 byte 0xFF şeklinde. bu mesajlardan birisi gelirse de dma buffer'ın kayar yine düzeltemezsin.

Mucitin söylediği gibi balşangıç ve bitiş karakterlerini kendine özel hale getirirsen hata oranı sıfıra  yakın olur.
receive rutinini dediğim gibi 1 byte olarak yapar ve başlangıç byte'ı gelmeden gelen her paketi görmezden gelip başlangıç paketiyle birlikte saymaya başlarsın ve 8. karakterin senin belirlediğin bitiş karakteri olup olmadığını kontrol edersin.
 8. paket bitiş karakteri değilse yine aldıklarını siler görmezden gelirsin sayaçlarını sıfırlarsın.
bu yöntemle mesaj kaçırabilirsin fakat kayma hatası 2 mesaj döngüsünde normale çekilir.

nextionda 3 farklı proje yaptım receive rutininin 1 den büyük olduğu her durumda kayma sorunu oldu. 1 byte parser en kullanışlı çözüm bence.

tamamdır dediklerinizi dikkate alarak yeni bir parser uygulayacağım.

isoment01

Alıntı yapılan: Mucit23 - 22 Nisan 2020, 10:34:23Gelen verileri byte byte al. Dma ile paket alımında senkronizasyon sorunu olabilir ki bence karakter kaçırmanın sebebi budur. Dma kullanıyorsan bile buffer boyutunu 1 yap. DMA Tc kesmesini aktif et. Bu sayede her bir karakter geldiğinde dma kesme oluşturacak sende kesme içerisinde karakter başı sonu vs gibi kontrolleri yaparsın. Bu şekilde yaparsan senkronizasyon sorunu yaşamazsın.
Hocam parser'i yapamadım. Sadece 1 bytelık veri alıyorum ve bu baytın ıcınde benım tum ıstedıgım bılgıler var ve 8 bitte dolu. Nextion tarafında ekrandakı butonlardakı tum verıler bıt kaydırma ıslemlerı ıle bır bayta sıgdırıldı. Bende alıcıda bunu parse ediyordum. Şimdi dediğiniz metodu yapmaya calıstım fakat algoritmayı kuramadım. Nextion tarafının kodlamasını baska bırısı yapıyor ve benım tek bıldıgım data frame'in formatı. Dedıgınızı yaparsam format şöyle mi olacak ? "0x71 * DATA # BOŞ 0xFF 0xFF 0xFF " Buffer'ı tek bayt ayarladıgımda bunları sırasıyla nasıl parse edeceğim ?

Mucit23

Nextion tarafında print komutu ile istediğiniz text'i gönderebilirsiniz. Bu işinizi çok kolaylaştırır. İlla standart frame gönderilmesine gerek yok. Fakat eğer başka birisi bu yazılımı yapıyor ve müdahale imkanı yok ise gelen paket içerisinde 0x71 karakter başı, 0xFF karakter sonu olarak kabul edilebilir. Aşağıdaki gibi bir algoritma kullanabilirsin.
if(usart1_state==0)
 {
 if(usart1_rx_data==0x71)
 {
 usart1_buffer_index=0;
 usart1_state=1;
 }
 }
 else
 {
 usart1_rx_buffer[usart1_buffer_index]=usart1_rx_data; //gelen yeni karakter pakete ekleniyor.
 usart1_buffer_index++;
 if(usart1_rx_data==0xFF)
 {
 usart1_rx_buffer[usart1_buffer_index]='\0'; //Paket sonu
 usart1_buffer_index=0;
 usart1_state=0;
 usart1_rx_flag=1;  //RX bayrağını set ediyoruz. 
 }
 }

Algoritma 0x71 gördüğü zaman gelen verileri buffer'a atmaya başlar, ilk olarak 0xFF görüldüğü anda paketi kapatır.

isoment01

Alıntı yapılan: Mucit23 - 22 Nisan 2020, 20:13:57Nextion tarafında print komutu ile istediğiniz text'i gönderebilirsiniz. Bu işinizi çok kolaylaştırır. İlla standart frame gönderilmesine gerek yok. Fakat eğer başka birisi bu yazılımı yapıyor ve müdahale imkanı yok ise gelen paket içerisinde 0x71 karakter başı, 0xFF karakter sonu olarak kabul edilebilir. Aşağıdaki gibi bir algoritma kullanabilirsin.
if(usart1_state==0)
 {
 if(usart1_rx_data==0x71)
 {
 usart1_buffer_index=0;
 usart1_state=1;
 }
 }
 else
 {
 usart1_rx_buffer[usart1_buffer_index]=usart1_rx_data; //gelen yeni karakter pakete ekleniyor.
 usart1_buffer_index++;
 if(usart1_rx_data==0xFF)
 {
 usart1_rx_buffer[usart1_buffer_index]='\0'; //Paket sonu
 usart1_buffer_index=0;
 usart1_state=0;
 usart1_rx_flag=1;  //RX bayrağını set ediyoruz. 
 }
 }

Algoritma 0x71 gördüğü zaman gelen verileri buffer'a atmaya başlar, ilk olarak 0xFF görüldüğü anda paketi kapatır.
hocam çok teşekkür ederim.