PELCO-D protokolü nedir?

Başlatan zakbay, 04 Aralık 2009, 18:20:48

Mucit23

Evet arkadaşlar Yine Saçma sapan bir sorunla karşı karşıyayım.

Sorunu çözdüm aslında kamerayı yönlendirebiliyorum. Donanımda problem yokmuş. Sorun Gönderici tarafında Transreciever entegresinin DIR pininde. STM32 ile ilgili başka bir problem var. Şöyle anlatayım.

RS485 üzerinden PelcoD protokolünde veri gönderirken SyncByte>>Adress>>Comman0>>Command1>>Data0>>Data1>>CheckSum olmak üzere 7 byte'dan oluşan paket göndermek gerekiyor.

Ben uarttan yukarıda yazdığım sıralamada SyncByte'ı göndermeden önce RS485_DIR pinini Lojik 1 yapıyorum. CheckSum'un tamamı gittikten sonrada Lojik sıfır yapıyorum. Bu iş için aşağıdaki kodları kullandım.

GPIO_SetBits(GPIOB,GPIO_Pin_2);  //Enable DIR
	 RS485_SendByte(PelcoD_Command->SyncByte);  //Write SyncByte
	 RS485_SendByte(PelcoD_Command->Adress);    //Write Adress
	 RS485_SendByte(PelcoD_Command->Command1);  //Write Command1
	 RS485_SendByte(PelcoD_Command->Command2);  //Write Command2
	 RS485_SendByte(PelcoD_Command->Data1);     //Write Data1
	 RS485_SendByte(PelcoD_Command->Data2);     //Write Data2
	 RS485_SendByte(CheckSum);                  //Write CheckSum
	 GPIO_ResetBits(GPIOB,GPIO_Pin_2); //Disable DIR


RS485_SendByte Fonksiyonumda aşağıdaki gibi.
void RS485_SendByte(u16 Data)
{ 
   USART3->DR = (Data & (uint16_t)0x00FF);
   while (!USART_GetFlagStatus(USART3,USART_FLAG_TXE)){}	 
}


Lojik analyserdan herşeyi izliyorum. Benim üzerinde çalıştığım mcu nun tx pini ile Kamera üzerinde bulunan işlemcinin(oda stm32f103) RX pinini lojik analyser'a bağladım. Aynı zamanda benim veri gönderdiğim taraftaki RS485_DIR Pinini de lojik analyser'a bağladım.
Sonuç aşağıdaki gibi.

gönderilen verilerde sıkıntı yok.  SyncByte>>Adress>>Comman0>>Command1>>Data0>>Data1>>CheckSum sırasında göre 7 byte data gidiyor. fakat Karşı tarafa CheckSum gitmeden RS485_DIR Pini 0 yapılıyor. Bu yüzden CheckSum karşıya gidemiyor. Giden veri anlaşılmıyor. Yani 1 byte önceden DIR Pini 0 yapılıyor. Bu her zaman böyle.

Bende CheckSumdan sonra DIR Pinin 0 yapmadan hemen önce 0xFF gönderdim.
GPIO_SetBits(GPIOB,GPIO_Pin_2);
	 RS485_SendByte(PelcoD_Command->SyncByte);  //Write SyncByte
	 RS485_SendByte(PelcoD_Command->Adress);    //Write Adress
	 RS485_SendByte(PelcoD_Command->Command1);  //Write Command1
	 RS485_SendByte(PelcoD_Command->Command2);  //Write Command2
	 RS485_SendByte(PelcoD_Command->Data1);     //Write Data1
	 RS485_SendByte(PelcoD_Command->Data2);     //Write Data2
	 RS485_SendByte(CheckSum);                  //Write CheckSum
	 RS485_SendByte(0xFF);                      //gereksiz veri. 
	 GPIO_ResetBits(GPIOB,GPIO_Pin_2);

Toplamda 8 byte data gitmiş oldu ama dir pini en sonki datayı gönderirken 0 olduğu için en son göndermiş olduğum 0xFF karşıya gitmedi dolayısıyla protokole uyumlu bir paket göndermiş oldum. Kamera böyle çalışıyor.

Dediğim durum aşağıdaki gibi.


Durumu daha iyi anlamak için debug yapıyorum. Paketleri teker teker gönderiyorum. Ve her göndermeden sonra lojik analyser ile RX TX ve DIR pinine bakıyorum. Debug yapınca sıkıntı yok gibi görünüyor. Bütün paket gidiyor en sonda DIR 0 yapılıyor.

Duruma anlam veremedim gerçekten Debugda düzgün çalışıp normalde düzgün çalışmamasını nasıl yorumlayabiliriz. Sankide RS485_SendByte(CheckSum);    komutu ile  GPIO_ResetBits(GPIOB,GPIO_Pin_2); komutu normal çalışmada yer değiştiriyor!

Varmı yorumlayabilecek olan. Kamerayı çalıştırdım. STM32 niye böyle davranıyor?

Karamel

#16
hocam durum cok basit.
     GPIO_SetBits(GPIOB,GPIO_Pin_2);  //Enable DIR
     RS485_SendByte(PelcoD_Command->SyncByte);  //Write SyncByte
     RS485_SendByte(PelcoD_Command->Adress);    //Write Adress
     RS485_SendByte(PelcoD_Command->Command1);  //Write Command1
     RS485_SendByte(PelcoD_Command->Command2);  //Write Command2
     RS485_SendByte(PelcoD_Command->Data1);     //Write Data1
     RS485_SendByte(PelcoD_Command->Data2);     //Write Data2
     RS485_SendByte(CheckSum);                  //Write CheckSum
     GPIO_ResetBits(GPIOB,GPIO_Pin_2); //Disable DIR


buradaki codelarinizda ornegin su code unuz RS485_SendByte(PelcoD_Command->SyncByte);   bu mantikla calisiyor.

uart birimi musaitmi? hayir değil. oyleyse musait olana kadar bekleyelim. musait olunca. (PelcoD_Command->SyncByte) bu bilgiyi uart tan gonderelim. ama gonderim baslayinca isi peripheral birim halletsin. biz bir alt satira gecelim.



simdi code unuzu daha simple bir hale getirelim. yukaridaki codeunuz aslinda soyle



set_dir;

while(!birseyler); send_birseyler;
while(!birseyler); send_birseyler;
while(!birseyler); send_birseyler;
while(!birseyler); send_birseyler;
while(!birseyler); send_birseyler;
while(!birseyler); send_birseyler;

reset_dir;



simdi zurnanin zirt dedigi yere geldik.

en sondaki su code RS485_SendByte(CheckSum);  icin microcontroller uart birimi musaitmi diye bakiyor. tamam musait diyor. DR registerina CheckSum degerini basip gondermeyi baslatiyor. hop bir alt satira geciyor ve DIR pinini disable ediyor. bakin daha karsi tarafa start biti gitmeye baslar baslamaz rs485 entegresi tranmitter ozelliginden receiver ozelligine geciyor.

logic analyzer ekranindan bunu basitce gozlemleyip yorumlayabilirsiniz.

sorunu olusturan ve durumu sacma sapan yapan sey library. yani library boyle calisiyor. siz icerideki while i goremediginiz ve systemin register seviyesini incelemediginiz icin aldaniyorsunuz. yada bunu ihmal ediyorsunuz. debug yaparken son veri sak diye uarttan ciktigi ve daha sonra DIR ucu disable edildigi icin sorunu goremiyorsunuz.

boyle yapmayin: 

 GPIO_SetBits(GPIOB,GPIO_Pin_2);
     RS485_SendByte(PelcoD_Command->SyncByte);  //Write SyncByte
     RS485_SendByte(PelcoD_Command->Adress);    //Write Adress
     RS485_SendByte(PelcoD_Command->Command1);  //Write Command1
     RS485_SendByte(PelcoD_Command->Command2);  //Write Command2
     RS485_SendByte(PelcoD_Command->Data1);     //Write Data1
     RS485_SendByte(PelcoD_Command->Data2);     //Write Data2
     RS485_SendByte(CheckSum);                  //Write CheckSum
     RS485_SendByte(0xFF);                      //gereksiz veri. 
     GPIO_ResetBits(GPIOB,GPIO_Pin_2);


gereksiz veri yerine 1 byte lik veri gonderimi suresi kadar delay koyun. CheckSum karsi tarafa gidince rs485 entegresi receiver olsun. sorun ortadan kalkar.




CLR

STM32 yanlış davranmıyor, düzgün çalışıyor. Problem senin gönderme fonksiyonunda.

Knowledge and Experience are Power

Mucit23

İyide Ben zaten RS485_SendByte Fonksiyonunun içerisinde TX_Bufferinin boşalmasını bekliyorum.

void RS485_SendByte(u16 Data)
{ 
   USART3->DR = (Data & (uint16_t)0x00FF);
   while (!USART_GetFlagStatus(USART3,USART_FLAG_TXE)){}	 
}


   while (!USART_GetFlagStatus(USART3,USART_FLAG_TXE)){}   
   Burada buffer boşalması bekleniyor. TX Buffer boşalmadan diğer byte gönderilmiyor.

Hatta yukarıdaki fonksiyonda fonksiyondan çıkmadan önce GPIO lardan birini toggle yapıp logic analyserde TX pini ile birlikte izledim. Hiçbir sıkıntı yok görünüyor. Tam olarak 1 byte veri gönderildikten sonra çıkış toggle yapılıyor. Bekleme olmasa eğer paketin başında vs toggle yapılırdı.

@Karamel senin dediğin mantıkta çalışıyor zaten program.

Muhtemelen gözümden kaçan birşey var. @CLR Sen problemi gördün gibi. Neyi eksik yapıyorum?

Karamel

#19
Alıntı yapılan: Mucit23 - 21 Temmuz 2015, 10:40:42
İyide Ben zaten RS485_SendByte Fonksiyonunun içerisinde TX_Bufferinin boşalmasını bekliyorum.

void RS485_SendByte(u16 Data)
{ 
   USART3->DR = (Data & (uint16_t)0x00FF);
   while (!USART_GetFlagStatus(USART3,USART_FLAG_TXE)){}	 
}


   while (!USART_GetFlagStatus(USART3,USART_FLAG_TXE)){}   
   Burada buffer boşalması bekleniyor. TX Buffer boşalmadan diğer byte gönderilmiyor.

Hatta yukarıdaki fonksiyonda fonksiyondan çıkmadan önce GPIO lardan birini toggle yapıp logic analyserde TX pini ile birlikte izledim. Hiçbir sıkıntı yok görünüyor. Tam olarak 1 byte veri gönderildikten sonra çıkış toggle yapılıyor. Bekleme olmasa eğer paketin başında vs toggle yapılırdı.

@Karamel senin dediğin mantıkta çalışıyor zaten program.

Muhtemelen gözümden kaçan birşey var. @CLR Sen problemi gördün gibi. Neyi eksik yapıyorum?


Single byte communication
The TXE bit is always cleared by a write to the data register.
The TXE bit is set by hardware and it indicates:
• The data has been moved from TDR to the shift register and the data transmission has
started.
• The TDR register is empty.
• The next data can be written in the USART_DR register without overwriting the
previous data.
This flag generates an interrupt if the TXEIE bit is set.



hocam USART_SR registerin da TC bitini test ederek yapabilirmisiniz?

soyle yani.

while(USART_SR->TC == 0);




mesaj birleştirme:: 21 Temmuz 2015, 14:05:04

bu arada yukaridaki code u direk copy paste yapmayin. keil da declaring nasil bilmiyorum. onu biz o bit 0 iken bekleyecegiz i anlatmak icin yazdim.

birde usart peripheral birim cok uzun. bunu okuyup tam anlamiyla anlamak icin 5-6 saat gerekli.

Mucit23

İlgin için teşekkürler. Ben gönderme fonksiyonlarında problem olduğunu sanmıyorum. Çünkü normal çalışmada
while (!USART_GetFlagStatus(USART3,USART_FLAG_TXE)){} satırından sonra GPIO pinin toggle yapıyorum. Daha önce demiştim paket bittiği anda Toggle işlemi oluyor. Yani Yukarıdaki satırda buferin boşalması bekleniyor.

Ciddi anlamda artık anlamakta zorlanıyorum. Çok basit bir yazım hatası vs olabilir diye düşünüyorum ama defalarca kodu inceledim.
@CLR nerde hata yapıyorum?

mufitsozen

Alıntı yapılan: Mucit23 - 21 Temmuz 2015, 16:19:25
İlgin için teşekkürler. Ben gönderme fonksiyonlarında problem olduğunu sanmıyorum. Çünkü normal çalışmada
while (!USART_GetFlagStatus(USART3,USART_FLAG_TXE)){} satırından sonra GPIO pinin toggle yapıyorum. Daha önce demiştim paket bittiği anda Toggle işlemi oluyor. Yani Yukarıdaki satırda buferin boşalması bekleniyor.

Ciddi anlamda artık anlamakta zorlanıyorum. Çok basit bir yazım hatası vs olabilir diye düşünüyorum ama defalarca kodu inceledim.
@CLR nerde hata yapıyorum?

Ben @CLR degilim ama, sorununuz transmission bitmesini degil, TX registerin bos olmasini bekliyorsunuz.

TXE biti degil TC bitini test edin gonderme bittimi diye(en sonda)
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

Mucit23

Denemedim ama sanırım haklısınız. TXE enable bitini bekleyince son bytte buffere yazıp beklemeden çıkıyordu fonksiyondan. hemen DIR disable yapılıyor. TC bitini bekleyince while içerisinde işlemci beklemek zorunda kalır. Hemen deneyeceğim.

CLR

Ben cevabı basit olduğu için hedef gösterip, kendin bulasın diye yazmamıştım ama @mufitsozen ve @Karamel cevabı yazmışlar. Müfit bey zaten biliyordur ama Karamel kendi işi olmadığı halde gidip registeri okuyup bulmuş. Zaten sadece bir status registerine bakmak gerekiyordu.
Knowledge and Experience are Power

OG

#24
Bir küçük donanım ayrıntısını hatırlatayım.
Her iki taraf dinlemede (RX) iken
MAX485 için
nRE = 0 , DE = 0 => A-B = High-Z
Bu durumda RO = 1 gösteriyor (MCU ya bağlı RX ucu) ancak A-B'nin High-Z durumu (hat yüzer halde) hat boyunca oluşabilecek elektriksel girişimler sebebi ile RO çıkışında belirsiz pulse lara sebep olabilir.

MAX485'in fonksiyon tablosu biraz daha güvenilir görünüyor, 75176 kullanırsanız bahsettiğim belirsiz durum daha yuksek ihtimal gibi.

Bunun önüne gecmek için A,B uçları pullup ve pulldown yapılıp, A-B arasına da bir kapatma direnci koyulur. Bakınız RS485 app notes.

Ben uygulamalarımda RO pinini de (MCU ya bağlı RX ucu) pullup yapıyorum.

MAX 485




resim yüke




SN75176




resim yükleme servisi
FORUMU İLGİLENDİREN KONULARA ÖM İLE CEVAP VERİLMEZ.

Mucit23

Aslında daha önce rs232 için sürekli kullandığım bir kütüphaneydi. Test için RS485 İçin kodları çevirmiştim.  Bende baska bir yerde almıştım.  Demek en baştan hatalıymış.

OG

Alıntı yapılan: Mucit23 - 21 Temmuz 2015, 20:37:38
Aslında daha önce rs232 için sürekli kullandığım bir kütüphaneydi. Test için RS485 İçin kodları çevirmiştim.  Bende baska bir yerde almıştım.  Demek en baştan hatalıymış.
Ne farkeder ki, protokol aynı, donanıma doğru hitap ettikçe aynı işler yapılıyor.
FORUMU İLGİLENDİREN KONULARA ÖM İLE CEVAP VERİLMEZ.

Mucit23

Yok hocam protokolü biliyorum.  TXE Bitini beklemek hatalıymış.

mufitsozen

Alıntı yapılan: Mucit23 - 21 Temmuz 2015, 21:07:00
Yok hocam protokolü biliyorum.  TXE Bitini beklemek hatalıymış.

demek ki karamel gibi yapip datasheet okumak lazimmis. Ne kadar biliyoruz zannetsekde yada yazdigimiz program bir sekilde daha once calisiyor gibi gozuksede, hata varsa referansimiz datasheet.
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

Mucit23

Şuan çalıştı. Haklısınız... Okuduğumu anlamakta zorlanıyorum.