2016-01-15 6 views
14

मेरे पास एक ऐसा एप्लिकेशन है जो rs232 के माध्यम से विभिन्न हार्डवेयर पढ़ता है। यह परीक्षण किया गया है और यह पूरी तरह से काम कर रहा था। अंतिम आवेदन के लिए मुझे कुछ हंडर मीटर लम्बी केबल पेश करने की आवश्यकता थी जिसका मतलब है कि मेरे पास rs485 कन्वर्टर्स हैं।लंबे केबल समय पर सीरियल संचार टाइमआउट

जब मैं हार्डवेयर पढ़ने के लिए अपना आवेदन चलाता हूं तो मुझे System.IO.Ports.SerialStream.Read के लिए एक टाइम आउट त्रुटि मिलती है। मैंने समय-समय पर 20sec में वृद्धि की है दुर्भाग्य से इस समस्या को हल नहीं किया

मैंने हार्डवेयर को पढ़ने के लिए विभिन्न अनुप्रयोगों का प्रयास किया है और उन्होंने 1sec पढ़ने की आवृत्ति के साथ भी काम किया है।

संचार मॉडबस प्रोटोकॉल का उपयोग कर रहा है, जो वर्तमान चरण में है, मुझे लगता है कि मैं कुछ भी प्राप्त करने के लिए मंच पर नहीं पहुंचता हूं।

मेरे कोड इस तरह दिखता है: पहले सीरियल पोर्ट खोलने और प्रारंभ:

//get the right modbus data structure element 
ModBus MB = (ModBus)s[0].sensorData; 

//set up the serial port regarding the data structure's data 
SerialPort sp = new SerialPort(); 
sp.PortName = MB.portName; 
sp.BaudRate = Convert.ToInt32(MB.baudRate); 
sp.DataBits = MB.dataBits; 
sp.Parity = MB.parity; 
sp.StopBits = MB.stopBits; 
//Set time outs 20 sec for now 
sp.ReadTimeout = 20000; 
sp.WriteTimeout = 20000; 

// एक सूची है जो पाठक portList.Add (सपा) द्वारा पहुँचा जा सकता करने के लिए बंदरगाह को जोड़ने; sp.Open();

पढ़ें हार्डवेयर:

//get the right port for com 
SerialPort sp = getRightPort(); 
ModBus MB = getRightModBusStructureelement(); 
try 
    { 
    //Clear in/out buffers: 
    sp.DiscardOutBuffer(); 
    sp.DiscardInBuffer(); 

    //create modbus read message 
    byte[] message = createReadModBusMessage(); 

    try 
     { 
     sp.Write(message, 0, message.Length); 

     // FM.writeErrorLog output included for easier debug 
     FM.writeErrorLog(DateTime.Now + ": ModBus Message Sent"); 
     FM.writeErrorLog(DateTime.Now + ": Read TimeOut = " + sp.ReadTimeout + " Write TimeOut = " + sp.WriteTimeout); 

     int offset = 0, bytesRead; 
     int bytesExpected = response.Length; 

     FM.writeErrorLog(DateTime.Now + ": start read"); 

     while (bytesExpected > 0 && (bytesRead = sp.Read(response, offset, bytesExpected)) > 0) 
      { 
       FM.writeErrorLog(DateTime.Now + ": read - " + offset); 
       offset += bytesRead; 
       bytesExpected -= bytesRead; 
      } 
     } 
     catch (Exception err) 
     { 
      Console.WriteLine("ERROR Modbus Message to serial port ModBus: " + err); 
      FM.writeErrorLog(DateTime.Now + " - " + "ERROR Modbus Message to serial port ModBus: " + err); 
     } 

    } 

आवेदन की कोशिश के बाद मैं ErroLog.txt से निम्नलिखित उत्पादन मिल गया:

14/01/2016 17:18:17: ModBus Message Sent 
14/01/2016 17:18:17: Read TimeOut = 20000 Write TimeOut = 20000 
14/01/2016 17:18:18: start read 
14/01/2016 17:18:38 - ERROR Modbus Message to serial port ModBus: System.TimeoutException: The operation has timed out. 
    at System.IO.Ports.SerialStream.Read(Byte[] array, Int32 offset, Int32 count, Int32 timeout) 
    at System.IO.Ports.SerialStream.Read(Byte[] array, Int32 offset, Int32 count) 
    at System.IO.Ports.SerialPort.Read(Byte[] buffer, Int32 offset, Int32 count) 
    at ProbReader.SensorReader.modbusReading(List`1 mm, Int32 spCounter) 
14/01/2016 17:18:38: 0 
14/01/2016 17:18:38: 0 

मैं टाइमआउट वृद्धि हुई है सिर्फ मामले में, लेकिन एक ही त्रुटि 60sec रहे हैं:

15/01/2016 11:11:51: ModBus Message Sent 
15/01/2016 11:11:51: Read TimeOut = 60000 Write TimeOut = 60000 
15/01/2016 11:11:51: start read 
15/01/2016 11:12:51 - ERROR Modbus Message to serial port ModBus: System.TimeoutException: The operation has timed out. 
    at System.IO.Ports.SerialStream.Read(Byte[] array, Int32 offset, Int32 count, Int32 timeout) 
    at System.IO.Ports.SerialStream.Read(Byte[] array, Int32 offset, Int32 count) 
    at System.IO.Ports.SerialPort.Read(Byte[] buffer, Int32 offset, Int32 count) 
    at ProbReader.SensorReader.modbusReading(List`1 mm, Int32 spCounter) 
15/01/2016 11:12:51: 0 
15/01/2016 11:12:51: 0 

मैंने धारावाहिक बंदरगाह पढ़ने के कुछ अलग तरीकों की कोशिश की है, मुझे लगता है कि टी वह वर्तमान विधि सबसे अच्छा दिखता है जो मेरे पढ़ने कोड में थोड़ी देर लूप है।

मैंने अपने शेष कोड को पहले के समय में शामिल नहीं किया था और मुझे लगता है कि यह अप्रासंगिक है।

+0

मुझे आरटीएस/सीटीएस जैसे हार्डवेयर प्रवाह नियंत्रण का कोई सबूत नहीं दिख रहा है। सॉफ़्टवेयर फ्लो-कंट्रोल से पहले भी मेरी पहली पसंद होगी जो मुझे संदेह है कि आपके परिस्थिति – MickyD

+0

में अविश्वसनीय है, इसके अलावा, आपका उपरोक्त कोड वास्तव में _ मूल्यों को दिखाता है जो आप _parity के लिए उपयोग कर रहे हैं; डेटा बिट्स; बॉड; बिट्स रोको; _ और बहुत आगे। किसी भी मौके पर आप 'एमबी' में मूल्यों को डंप कर सकते हैं? – MickyD

+0

क्या आपने COM से आईपी कनवर्टर का उपयोग करने के बारे में सोचा है? फिर आप एक टीसीपी-सॉकेट के माध्यम से अपना डेटा प्राप्त कर सकते हैं और आप एक लंबी दूरी को संभालने में सक्षम हो सकते हैं। – etalon11

उत्तर

1

जैसा कि मैंने अपने प्रश्न में उल्लेख किया है, मैं हार्डवेयर को अन्य सॉफ़्टवेयर के साथ पढ़ने में सक्षम था, इसलिए इसे सॉफ़्टवेयर त्रुटि होने की आवश्यकता थी। जांच के बाद सभी संभव चर मैं सीरियल पोर्ट सेटिंग में हेरफेर कर सकता हूं, मैंने हैंडशेक को बदलने और इसे हमेशा स्वीकार करने के विचार के साथ आ गया है।

चारों ओर खोदने का एक छोटा सा हिस्सा मुझे लिखने और पढ़ने का समय बढ़ाने के साथ निम्नलिखित कोड देता है। इसने मेरी समस्या हल की:

      sp.ReadTimeout = 60000; 
          sp.WriteTimeout = 60000; 

          sp.DtrEnable = true; 
          sp.RtsEnable = true; 
          sp.Handshake = Handshake.None; 

मुझे उम्मीद है कि यह भविष्य में दूसरों के लिए मदद करेगा, और हर किसी की मदद और प्रयास के लिए धन्यवाद।

2

इस एक हार्डवेयर/लंबे केबल मुद्दा मानते हुए नहीं है, आप में सक्षम हो सकता त्रुटि को संभालने के लिए अपने कोड में कुछ करना:

आप के रूप में ज्यादा एक "सही" त्रुटि हैंडलर बनाने के लिए के रूप में आप getRightPort बनाने की जरूरत है:

SerialPort sp = getRightPort(); 

मान लिया जाये कि वहाँ सीरियल पोर्ट आइटम के अंदर की एक Collection है और आप सही एक वापसी, इस SerialPort के मामले में किया गया है त्रुटि, सुनिश्चित करें कि आप फिर से बनाने त्रुटि एक ही सेटिंग्स के साथ SerialPortobject:

catch (Exception err) 
{ 
    Console.WriteLine("ERROR Modbus Message to serial port ModBus: " + err); 
    FM.writeErrorLog(DateTime.Now + " - " + "ERROR Modbus Message to serial port ModBus: " + err); 
    reinitRightPort(sp); //add this 
} 

और विधि reinitRightPort(); कैसे आप पहली बार शुरू करने के लिए समान लग सकता है, छोटे मतभेदों की तरह साथ :

  1. आप अब List<SerialPort> में जोड़ने के लिए
  2. आप नहीं करने के लिए क्या जरूरत नहीं है विधि में SerialPort घोषित करें, आप इसे इनपुट तर्क से प्राप्त करते हैं।
  3. यह सबसे अच्छा हो सकता है कुछ इनपुट की जांच वैधता बाद में ज्ञात त्रुटियों
  4. से बचने के लिए लागू करने के लिए शायद आप पिछले कनेक्शन बंद कर सकते हैं, बस यह सुनिश्चित करें कि बंदरगाह नई SerialPortobject द्वारा इस्तेमाल किया जा सकता बनाने के लिए।

कुछ इस तरह:

private void reinitRightPort(SerialPort sp){ //get SerialPort from outside of method 
    //Add whatever necessary here, to close all the current connections 
    //Plus all the error handlings 
    if (sp == null) //Read 3. 
     return; 
    sp.Close(); //Read 4. close the current connections 

    //get the right modbus data structure element 
    ModBus MB = (ModBus)s[0].sensorData; 

    //set up the serial port regarding the data structure's data 
    sp = new SerialPort(); //Read 2. sp is from outside the method, but use new keyword still 
    sp.PortName = MB.portName; 
    sp.BaudRate = Convert.ToInt32(MB.baudRate); 
    sp.DataBits = MB.dataBits; 
    sp.Parity = MB.parity; 
    sp.StopBits = MB.stopBits; 
    //Set time outs 20 sec for now 
    sp.ReadTimeout = 20000; 
    sp.WriteTimeout = 20000; 

    //portList.Add(sp); Read 1. no need to add this! It is already there! 
    sp.Open(); 
} 

नोट: के बाद आप ऐसा कर और सुनिश्चित करें कि आपके बंदरगाह में अच्छी तरह से काम कर रहा है, जब भी संभव हो, आप भी reinitRightPort विधि से ऊपर कुछ के साथ अपने वास्तविक प्रारंभ के साथ गठबंधन कर सकता है थोड़ा बदलाव लेकिन पहली चीज जो आप करना चाहते हैं वह है कि आपका सीरियल पोर्ट त्रुटि के तहत काम करता है।

But if the error source comes from hardware/long cable issue (such as cable placing in the RS232 or RS485, or voltage drop due to long cable, or incompatible hardware: that is, in short, nothing to do with coding at all), then, unfortunately the solution cannot come from code as well. You got to find the real hardware issue.

5

आप सीरियल केबल (जो अपने आप में एक हार्डवेयर इंजीनियरिंग समस्या है) के मीटर के सैकड़ों का उपयोग कर रहे हैं तो मैं दृढ़ता से केबल के दोनों सिरों पर एक उचित ट्रांसीवर रखें। केबल स्वयं ईएमसी संरक्षित और उच्च गुणवत्ता वाला होना चाहिए। असीमित केबल के लंबे रन प्रेरित वोल्टेज उतार-चढ़ाव के पीड़ित हो सकते हैं जो लंबे केबल रनों को संभालने के लिए डिज़ाइन नहीं किए गए उपकरणों को नुकसान पहुंचा सकते हैं।

अच्छी केबल के साथ भी आपके पास अभी भी काफी वोल्टेज बूंद और अपरिवर्तनीय/कैपेसिटिव प्रभाव होंगे जो उच्च बॉड दरों पर संचार को रोक सकते हैं। सबसे कम बॉड दर पर भागो जिसे आप दूर कर सकते हैं।

+0

केबल के सैकड़ों मीटर अपरिहार्य थे। केबल अच्छी गुणवत्ता है, वोल्टेज ड्रॉप एक मुद्दा नहीं होना चाहिए जैसा कि मैंने उल्लेख किया है कि मैं हार्डवेयर को अन्य सॉफ़्टवेयर के साथ पढ़ने में सक्षम था। हाथ हिलाकर हटाकर इस मुद्दे को हल करने के लिए प्रबंधित किया गया। हटाने पर मेरा मतलब है कि मैं इसे सत्य मानता हूं। – Daniel

4

मान लें कि यह एक हार्डवेयर समस्या है (और मुझे लगता है कि, मुझे भी इसी तरह की समस्या का समाधान करना पड़ा), मैं एक डिवाइस सर्वर (ईथरनेट के माध्यम से) के सैकड़ों मीटर सीरियल केबल को प्रतिस्थापित करने की सिफारिश करता हूं सीरियल डिवाइस। डिवाइस सर्वर आपके पीसी पर एक COM-Port अनुकरण कर सकता है और इसलिए सीरियल केबल को छोटा रखता है।

दुर्भाग्य से उन सर्वरों केबल के कुछ ही मीटर की दूरी पर की तुलना में थोड़ा अधिक महंगे हैं ..

+1

@ मिकी डी, ईथरनेट को लंबे केबल रनों के साथ दिमाग में बनाया गया है। सीरियल केबल्स आमतौर पर नहीं हैं। ईथरनेट एडाप्टर के लिए सीरियल इस समस्या का एक वैध समाधान है। दूरी अभी भी लंबी है लेकिन ईथरनेट इसे टिक्स्ड जोड़ी निर्माण के कारण बेहतर तरीके से संभालती है और संरक्षित रूप में उपलब्ध है। – Wossname

+0

@Wossname ओह, मैं देखता हूं कि अब आप क्या कह रहे हैं - ईथरनेट कन्वर्टर्स से सीरियल जैसे कि डिवाइस को पता नहीं है कि केबल ईथरनेट के साथ बदल दिया गया था। मेरा बुरा हेहे यहां +1 :) – MickyD

3

कृपया ध्यान दें कि RS232 और RS485 के बीच एक अंतर है कि RS232 फुल डुप्लेक्स है, जबकि 485 रुपये केवल आधा द्वैध है। चूंकि मोडबस एक अनुरोध प्रतिक्रिया प्रकार प्रोटोकॉल है, यह आपकी समस्या नहीं है लेकिन यह जानना महत्वपूर्ण है।

इसके कारण एक आरएस 232 < -> आरएस 485 को यह पता होना चाहिए कि इसके आरएस 485 ट्रांसमीटर को कब चालू करना है। यह विभिन्न कन्वर्टर्स पर अलग-अलग किया जा सकता है और कॉन्फ़िगर करने योग्य भी हो सकता है। यह अतिरिक्त नियंत्रण लाइनों के साथ किया जा सकता है जो आरएस 232 है लेकिन आरएस 485 की कमी है। आरटीएस/सीटीएस। यदि गलत प्रतिक्रियापूर्वक प्रतिसाद पक्ष (जो प्रतिक्रिया देने के अनुरोध की प्रतीक्षा करता है) को कॉन्फ़िगर किया गया हो तो ट्रांसमीटर हो सकता है और फिर उसे कुछ भी प्राप्त नहीं हो सकता है।

मैनुअल में एक उदाहरण http://ftc.beijer.se/files/C125728B003AF839/992C59EC02C66E00C12579C60051484E/westermo_ug_6617-2203_mdw-45.pdf यह स्वीडन में एक लोकप्रिय मॉडल है जिसमें ऑपरेशन के तीन तरीके हैं। यह सिर्फ आने वाले डेटा, डीबी 9-RS232 कनेक्टर पर RTS पिन द्वारा नियंत्रित द्वारा/बंद ट्रांसमीटर को चालू करने या हमेशा पर (RS422 प्रत्येक दिशा में अलग तारों है कि के लिए) ट्रांसमीटर हो सकता है http://screencast.com/t/KrkEw13J8

यह कठिन है क्योंकि कुछ मैन्युफैक्चरर्स प्रिंट नहीं करते हैं कि यह वास्तव में कैसे काम करता है। तारों को गलत करने के लिए यह भी बेहद आसान है क्योंकि यह स्पष्ट नहीं है कि डीसीई और डीटीई क्या है।

संबंधित मुद्दे