सीरियल संचार Arduino पर कैसे काम करता है?


16

Arduino Uno, Mega2560, लियोनार्डो और इसी तरह के बोर्डों के संदर्भ में:

  • धारावाहिक संचार कैसे काम करता है?
  • सीरियल कितनी जल्दी है?
  • मैं एक प्रेषक और रिसीवर के बीच कैसे जुड़ूं?

कृपया ध्यान दें: यह एक संदर्भ प्रश्न के रूप में है।


करें: आप नैनो एक Raspian एक अजगर चल डेटा लकड़हारा प्रणाली से जुड़े, के बीच दो बस एक नियमित रूप से यूएसबी प्रोग्रामिंग केबल का उपयोग कर एक के दोनों किनारों पर बफ़र्स के बारे में इस दिलचस्प लग सकते arduino.stackexchange.com/questions/11710/...
SDsolar

जवाबों:


16

अतुल्यकालिक धारावाहिक (आमतौर पर धारावाहिक के रूप में संदर्भित) संचार का उपयोग बाइट्स को एक डिवाइस से दूसरे में भेजने के लिए किया जाता है। एक उपकरण निम्नलिखित में से एक या अधिक हो सकता है:

  • Arduino
  • पीसी
  • GPS
  • आरएफआईडी कार्ड रीडर
  • एलसीडी प्रदर्शन
  • मोडम
  • अन्य

घड़ी की दर और डेटा का नमूना

एसपीआई / यूएसबी / आई 2 सी सीरियल संचार के विपरीत एक घड़ी संकेत नहीं है। सैंपलिंग क्लॉक एक सहमति-प्राप्त नमूना दर (बॉड दर के रूप में जाना जाता है) है। प्रेषक और रिसीवर दोनों को समान दर का उपयोग करने के लिए कॉन्फ़िगर किया जाना चाहिए या रिसीवर को अर्थहीन डेटा प्राप्त होगा (बिट्स को उसी दर पर नमूना नहीं किया जा सकता है जो उन्हें भेजा गया था)।

संचरण अतुल्यकालिक है जिसका मूल अर्थ है कि बाइट्स को किसी भी समय भेजा जा सकता है, उनके बीच अंतर अलग-अलग हो सकता है। यह ग्राफिक भेजे गए एक बाइट को दिखाता है:

सीरियल कॉमिक्स - एक बाइट भेजना

ऊपर दिया गया ग्राफिक 'F' अक्षर को प्रेषित करता है। ASCII में यह 0x46 (हेक्स में) या 0b01000110 (बाइनरी में) है। सबसे कम महत्वपूर्ण (कम-क्रम) बिट पहले प्रसारित किया जाता है, इस प्रकार उपरोक्त ग्राफिक में आप बिट्स को क्रम में आते हुए देखते हैं 01100010:।

बाइट्स के बीच "निष्क्रिय" समय को निरंतर "1" बिट्स के रूप में प्रेषित किया जाता है (प्रभावी रूप से, ट्रांसमिट लाइन को लगातार उच्च आयोजित किया जाता है)।

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

  • प्रारंभ बिट को छोड़ देता है
  • अगले बिट के माध्यम से आधे रास्ते के नमूने

यदि बॉड दर 9600 बॉड है, उदाहरण के लिए, तो नमूना दर 1/9600 = 0.00010416सेकंड (104.16 is) होगी।

इस प्रकार, 9600 बॉड में, एक स्टार्ट बिट प्राप्त करने के बाद रिसीवर 156.25 ba के लिए प्रतीक्षा करता है, और फिर प्रत्येक 104.16 6 के नमूने लेता है।

थोड़ा समय शुरू करें

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

ऊनो पर उपरोक्त आउटपुट को बनाने के लिए आप यह कोड लिख सकते हैं:

void setup()
  {
      Serial.begin(9600);
      Serial.print("F");
  }

void loop ()
  {
  }

डेटा बिट्स की संख्या

संचरण समय (पुराने दिनों में, हे) को बचाने के लिए आपको विभिन्न डेटा बिट्स को निर्दिष्ट करने की अनुमति दी गई थी। AtMega हार्डवेयर 5 से 9 तक डेटा बिट्स का समर्थन करता है। स्पष्ट रूप से कम डेटा बिट्स कम जानकारी जिसे आप भेज सकते हैं, लेकिन यह जितनी तेज़ी से होगा।


पैरिटी बिट्स

आप वैकल्पिक रूप से एक समता बिट कर सकते हैं। यह गणना की जाती है, यदि आवश्यक हो, तो वर्ण में 1 की संख्या की गणना करके, और फिर यह सुनिश्चित करना कि यह संख्या विषम है या यहां तक ​​कि आवश्यकतानुसार समता बिट को 0 या 1 पर सेट करके।

उदाहरण के लिए, "एफ" (या 0x46 या 0b01000110) पत्र के लिए आप देख सकते हैं कि वहां 3 लोग हैं (01000110 में)। इस प्रकार हमारे पास पहले से ही विषम समता है। तो, समता बिट निम्नानुसार होगा:

  • कोई समानता नहीं: छोड़ा गया
  • समता: यहां तक ​​कि एक 1 (3 + 1 सम है)
  • विषम समता: एक 0 (3 + 0 विषम)

समता बिट, यदि मौजूद है, तो अंतिम डेटा बिट के बाद दिखाई देता है लेकिन स्टॉप बिट से पहले।

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

कुछ प्रारंभिक प्रणालियों ने "मार्क" समानता का उपयोग किया (जहां डेटा की परवाह किए बिना समता बिट हमेशा 1 थी), या "स्पेस" समानता (जहां डेटा की परवाह किए बिना समानता हमेशा 0 थी)।


9-बिट ट्रांसमिशन

कुछ संचार उपकरण 9-बिट डेटा का उपयोग करते हैं, इसलिए इन मामलों में समता बिट को 9 वें बिट में बदल दिया जाता है। इस 9 वीं बिट को भेजने के लिए विशेष तकनीकें हैं (रजिस्टर 8-बिट रजिस्टर हैं इसलिए 9 वें बिट को कहीं और रखा जाना है)।


स्टॉप बिट्स की संख्या

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

यदि रिसीवर को लॉजिकल 1 नहीं मिलता है जब स्टॉप बिट माना जाता है, तो उसे "फ़्रेमिंग एरर" कहा जाता है। यह इंगित करता है कि कुछ समस्या है। काफी संभवत: प्रेषक और रिसीवर अलग-अलग बॉड (बिट) दरों का उपयोग करने के लिए कॉन्फ़िगर किए गए हैं।


नोटेशन

आमतौर पर, सीरियल संचार आपको गति, डेटा बिट्स की संख्या, समानता के प्रकार और स्टॉप बिट्स की संख्या बताकर संकेत दिया जाता है, जैसे:

9600/8-N-1

यह हमें बता रहा है:

  • 9600 बिट्स प्रति सेकंड
  • 8 डेटा बिट्स
  • कोई समानता (आप इसके बजाय देख सकते हैं: E = सम, O = विषम)
  • 1 स्टॉप बिट

यह महत्वपूर्ण है कि प्रेषक और रिसीवर उपरोक्त पर सहमत हों, अन्यथा संचार सफल होने की संभावना नहीं है।


पिन बहिष्कार

Arduino Uno में डिजिटल सीरियल के लिए डिजिटल पिन 0 और 1 उपलब्ध है:

Arduino Uno सीरियल पिन

दो Arduinos को जोड़ने के लिए आप Tx और Rx को इस तरह स्वैप करें:

दो Arduinos को एक साथ जोड़ना


गति

गति की एक विस्तृत श्रृंखला समर्थित है (नीचे ग्राफिक देखें)। "मानक" गति आमतौर पर 300 बॉड के कई (जैसे 300/600/1200/2400 आदि) हैं।

अन्य "गैर-मानक" गति को उचित रजिस्टर सेट करके नियंत्रित किया जा सकता है। HardwareSerial वर्ग आपके लिए ऐसा करता है। जैसे।

Serial.begin (115200);  // set speed to 115200 baud

एक नियम-से-अंगूठे के रूप में, मान लें कि आप 8-बिट डेटा का उपयोग कर रहे हैं, तो आप बाइट्स की संख्या का अनुमान लगा सकते हैं जिसे आप 10 से बॉड दर को विभाजित करके शुरू कर सकते हैं (शुरुआत बिट और स्टॉप बिट के कारण)।

इस प्रकार, 9600 बॉड पर आप 9600 / 10 = 960प्रति सेकंड 960 बाइट्स ( ) प्रसारित कर सकते हैं ।


बॉड दर त्रुटियों

एटमेगा पर बॉड दर सिस्टम घड़ी को विभाजित करके उत्पन्न होती है, और फिर एक पूर्व-निर्धारित संख्या तक गिनती होती है। डेटशीट की यह तालिका 16 मेगाहर्ट्ज की घड़ी (जैसे कि अरुडिनो उनो) के लिए रजिस्टर मान और त्रुटि प्रतिशत दर्शाती है।

बॉड दर त्रुटियों

U2Xn बिट घड़ी दर भाजक (0 = 16 से विभाजित, 1 = 8 से विभाजित) को प्रभावित करता है। UBRRn रजिस्टर में वह संख्या होती है जो प्रोसेसर तक गिना जाता है।

तो ऊपर दी गई तालिका से, हम देखते हैं कि हम 16 मेगाहर्ट्ज घड़ी से 9600 बॉड प्राप्त करते हैं:

16000000 / 16 / 104 = 9615

हम 104 से विभाजित करते हैं और 103 नहीं, क्योंकि काउंटर शून्य-सापेक्ष है। इस प्रकार यहां त्रुटि है 15 / 9600 = 0.0016जो ऊपर दी गई तालिका के करीब है (0.02%)।

आप देखेंगे कि कुछ बॉड दरों में दूसरों की तुलना में उच्च त्रुटि राशि है।

डेटाशीट के अनुसार 8 डेटा बिट्स के लिए अधिकतम त्रुटि प्रतिशत 1.5% से 2.0% (अधिक विवरण के लिए डेटा पत्रक देखें) की सीमा में है।


अरुडिनो लियोनार्डो

Arduino लियोनार्डो और माइक्रो का धारावाहिक संचार के लिए एक अलग दृष्टिकोण है, क्योंकि वे सीधे USB के माध्यम से होस्ट कंप्यूटर से कनेक्ट होते हैं, सीरियल पोर्ट के माध्यम से नहीं।

इस वजह से, आपको सीरियल के लिए "तैयार" होने का इंतजार करना होगा (जैसा कि सॉफ्टवेयर एक यूएसबी कनेक्शन स्थापित करता है), इस तरह की एक अतिरिक्त जोड़ी के साथ:

void setup()
  {
      Serial.begin(115200);
      while (!Serial)
      {}  // wait for Serial comms to become ready
      Serial.print("Fab");
  }

void loop ()
  {
  }

हालाँकि, यदि आप वास्तव में पिन D0 और D1 के माध्यम से संवाद करना चाहते हैं, (USB केबल के बजाय) तो आपको Serial1 का उपयोग Serial के बजाय करने की आवश्यकता है। आप ऐसा करते हैं:

void setup()
  {
      Serial1.begin(115200);
      Serial1.print("Fab");
  }

void loop ()
  {
  }

वोल्टेज का स्तर

ध्यान दें कि Arduino सीरियल संचार के लिए TTL स्तरों का उपयोग करता है। इसका मतलब है कि यह उम्मीद करता है:

  • एक "शून्य" बिट 0 वी है
  • एक "एक" बिट + 5 वी है

पुराने सीरियल उपकरण जिसे पीसी के सीरियल पोर्ट में प्लग करने के लिए डिज़ाइन किया गया है, संभवतः RS232 वोल्टेज स्तर का उपयोग करता है, अर्थात्:

  • एक "शून्य" बिट +3 से +15 वोल्ट है
  • एक "एक" बिट −3 से ts15 वोल्ट है

न केवल TTL स्तरों के संबंध में यह "उलटा" है ("शून्य" की तुलना में "एक" अधिक नकारात्मक है), Arduino अपने इनपुट पिंस पर नकारात्मक वोल्टेज को संभाल नहीं सकता है (न ही सकारात्मक 5V से अधिक)।

इस प्रकार आपको ऐसे उपकरणों के साथ संचार करने के लिए एक इंटरफ़ेस सर्किट की आवश्यकता होती है। इनपुट के लिए (Arduino के लिए) केवल, एक साधारण ट्रांजिस्टर, डायोड, और प्रतिरोधों के एक जोड़े यह करेंगे:

इनवर्टर बफर

दो-तरफ़ा संचार के लिए आपको नकारात्मक वोल्टेज उत्पन्न करने में सक्षम होने की आवश्यकता होती है, इसलिए अधिक जटिल सर्किट की आवश्यकता होती है। उदाहरण के लिए MAX232 चिप चार्ज-पंप सर्किट के रूप में कार्य करने के लिए चार 1 itorsF कैपेसिटर के साथ संयोजन में ऐसा करेगी।


सॉफ्टवेयर सीरियल

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


Mega2560

Arduino "Mega" में 3 अतिरिक्त हार्डवेयर सीरियल पोर्ट हैं। वे बोर्ड पर Tx1 / Rx1, Tx2 / Rx2, Tx3 / Rx3 के रूप में चिह्नित हैं। यदि संभव हो तो उन्हें SoftwareSerial की प्राथमिकता में उपयोग किया जाना चाहिए। उन अन्य पोर्ट को खोलने के लिए, जिन्हें आप Serial1, Serial2, Serial3, जैसे नामों से उपयोग करते हैं:

Serial1.begin (115200);  // start hardware serial port Tx1/Rx1
Serial2.begin (115200);  // start hardware serial port Tx2/Rx2
Serial3.begin (115200);  // start hardware serial port Tx3/Rx3

बीच में आता है

HardwareSerial लाइब्रेरी का उपयोग करते हुए भेजने और प्राप्त करने, दोनों का उपयोग करना।

भेजना

जब आप एक करते हैं Serial.print, तो आप जिस डेटा को प्रिंट करने की कोशिश कर रहे हैं, उसे आंतरिक "ट्रांसमिट" बफर में रखा गया है। यदि आपके पास 1024 बाइट्स या अधिक RAM (जैसे कि Uno पर) आपको 64-बाइट बफर मिलता है, अन्यथा आपको 16-बाइट बफर मिलता है। यदि बफर में कमरा है, तो Serial.printतुरंत रिटर्न देता है, इस प्रकार आपके कोड में देरी नहीं होती है। यदि कोई कमरा नहीं है, तो यह "ब्लॉक" करता है कि बफर के इंतजार में वहां कमरा होना चाहिए।

फिर, जैसा कि प्रत्येक बाइट को हार्डवेयर द्वारा प्रेषित किया जाता है, एक बाधा कहलाती है ("USART, डेटा रजिस्टर खाली" रुकावट) और अंतराक्रिया रूटीन धारावाहिक पोर्ट से बफर से अगला बाइट भेजता है।

प्राप्त करना

जैसा कि आने वाले डेटा को एक इंटरप्ट रूटीन कहा जाता है ("USART Rx कम्प्लीट" इंटरप्ट) और आने वाली बाइट को "रिसीव" बफर (ऊपर बताए गए ट्रांसफ़ॉर्म बफर के समान आकार) में रखा जाता है।

जब आप कॉल Serial.availableकरते हैं तो आपको पता चलता है कि उस "प्राप्त" बफर में कितने बाइट्स उपलब्ध हैं। जब आप Serial.readएक बाइट को कॉल करते हैं तो प्राप्त बफर से हटा दिया जाता है और अपने कोड पर वापस आ जाता है।

1000 बाइट्स या अधिक RAM वाले Arduinos पर, प्राप्त बफ़र से डेटा निकालने की कोई जल्दी नहीं है, बशर्ते आप इसे भरने न दें। यदि यह भर जाता है तो आने वाले किसी भी डेटा को छोड़ दिया जाता है।

ध्यान दें कि इस बफ़र के आकार के कारण बहुत बड़ी संख्या में बाइट्स के आने की प्रतीक्षा करने का कोई मतलब नहीं है, उदाहरण के लिए:

while (Serial.available () < 200)
  { }  // wait for 200 bytes to arrive

यह कभी काम नहीं करेगा क्योंकि बफर इतना नहीं पकड़ सकता है।


टिप्स

  • पढ़ने से पहले, हमेशा सुनिश्चित करें कि डेटा उपलब्ध है। उदाहरण के लिए, यह गलत है:

    if (Serial.available ())
      {
          char a = Serial.read ();
          char b = Serial.read ();  // may not be available
      }

    Serial.availableपरीक्षण केवल सुनिश्चित करता है आप एक तथापि कोड दो पढ़ने का प्रयास बाइट उपलब्ध,। यह काम कर सकता है, यदि बफ़र में दो बाइट्स हैं, तो नहीं, तो आपको -1 लौटाया जाएगा जो मुद्रित होने पर '' 'की तरह दिखेगा।

  • डेटा भेजने में कितना समय लगता है, इसके बारे में जानकारी रखें। जैसा कि ऊपर उल्लेख किया गया है, 9600 बॉड में आप प्रति सेकंड केवल 960 बाइट्स प्रसारित करते हैं, इसलिए एनालॉग पोर्ट से 1000 रीडिंग को 9600 बॉड में भेजने की कोशिश करना बहुत सफल नहीं होगा।


संदर्भ


1 ग्राफिक में: तीर के साथ ऐसा लगता है कि स्टॉप बिट पहले प्रसारित होता है। यदि आपने Rx / Tx का आदान-प्रदान किया है और तीर की दिशा मुझे लगता है कि यह कम भ्रामक है।
ott--

यह बाईं ओर से दाईं ओर पढ़ा जाना था (जैसा कि यह वाक्य है) और इस प्रकार बाईं ओर की चीजें पहले होती हैं। इसे इस तरह रखें: एक आस्टसीलस्कप पर, यह है कि आप ट्रेस कैसे देखेंगे।
निक गैमन

ठीक है, ऑसिलोस्कोप विस्फोट के साथ मैं इसे खरीदता हूं। :-)
ott--

हालाँकि मैं सोच रहा था कि आपकी बात बहुत मायने रखती है। दूसरे क्या सोचते हैं? क्या यह स्पष्ट होगा यदि तीर उलट गए थे, और मैंने आरएक्स / टीएक्स का आदान-प्रदान किया?
निक गैमन

1
@ linhartr22 मैंने इसे "अर्थहीन डेटा" पढ़ने के लिए संशोधित किया, जो संभवतः करीब है।
निक गैमन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.