Arduino और मेरे कंप्यूटर पर एक प्रोसेसिंग स्केच के बीच अंतराल को कम करना


13

मैं वर्तमान में Arduino प्रोजेक्ट पुस्तक के प्रोजेक्ट # 14 पर हूँ।

मैं अपने Arduino का उपयोग करके अपने लैपटॉप पर एक प्रोसेसिंग स्केच को नियंत्रित करने की कोशिश कर रहा हूं। यह एक छवि की पृष्ठभूमि को नियंत्रित करने के लिए एक पोटेंशियोमीटर का उपयोग करके पूरा किया जाता है।

Arduino कोड:

void setup(){
  Serial.begin(9600);
}

void loop(){
  Serial.write(analogRead(A0)/4);
}

प्रोसेस हो रहा है:

//imports serial library
import processing.serial.*;
//setups the serial object
Serial myPort;
//creates an object for the image
PImage logo;
//variable to store background color
int bgcolor = 0;

void setup(){
  colorMode(HSB,255);
  logo = loadImage("http://arduino.cc/logo.png");
  size(logo.width,logo.height);
  println("Available serial ports");
  println(Serial.list());
  myPort = new Serial(this,Serial.list()[0],9600);
}
//equivalent of arduino's loop function
void draw(){
  if(myPort.available() > 0)
  {
    bgcolor = myPort.read();
    println(bgcolor);
  }

  background(bgcolor,255,255);
  image(logo,0,0);
}

अब, जबकि कोड काम करता है, और जैसे ही मैं पोटेंशियोमीटर को बदलता है, पृष्ठभूमि का रंग बदल जाता है, पोटेंशियोमीटर को मोड़ने और पृष्ठभूमि के रंग को देखने के बीच एक बड़ा अंतराल होता है, और प्रसंस्करण के सीरियल मॉनीटर पर अरुडिनो / पोटेंशियोमीटर से मान बदलते हैं।

मैंने क्या कोशिश की है:

  • सीरियल संचार की गति को बदलना

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

फ्लिप की तरफ, 9600 की मानक गति पर, देरी बहुत बड़ी है, लगभग 5sec ++ लैपटॉप / प्रोसेसिंग पर पोटेंटियोमीटर शो में परिवर्तन से पहले।

संचार की गति (एक निश्चित बिंदु तक) घटने से समय अंतराल कम हो जाता है, और इसे बढ़ाने से समय अंतराल बढ़ जाता है? इसके अलावा, वहाँ वैसे भी मैं इसे तात्कालिक के पास कर सकता हूँ?


3
आप Arduino पर हर बार एक रीडिंग आउटपुट कर रहे हैं loop()। यह बहुत संभव है कि आपका प्रोसेसिंग प्रोग्राम इतनी तेजी से नहीं चल रहा है कि वह उसके साथ बना रहे। loop()इसे धीमा करने के लिए अपने Arduino कोड में देरी डालने की कोशिश करें ; उदा delay(50)
पीटर ब्लूमफील्ड

हाय पीटर, शीघ्र उत्तर के लिए धन्यवाद, एक छोटी सी देरी को जोड़ने से वास्तव में मेरी समस्या हल हो गई। हालांकि एक और छोटा सा सवाल है, क्या भविष्य में मैं अपने प्रसंस्करण कार्यक्रम की गति को निर्धारित कर सकता हूं ताकि इसे फिर से होने से रोका जा सके, या बेहतर लैपटॉप / प्रसंस्करण गति प्राप्त करने से समस्या का समाधान हो सके? इसके अलावा, क्यों arduino से रीडिंग 250 या 300 की संचार गति में प्रवेश करती है? (मुझे जो रीडिंग मिलती है वह रीडिंग और शून्य के बीच वैकल्पिक हैं। 147,0,147,0)
केनेथ .J

जवाबों:


11

आप Arduino के चक्कर में हर बार एक रीडिंग का उत्पादन कर रहे हैं loop(), इसलिए यह संभावना है कि आपका प्रोसेसिंग प्रोग्राम इतनी तेजी से नहीं चल रहा है कि वह इसके साथ बना रहे। loop()अपने Arduino कोड में देरी करने की कोशिश करें ताकि इसे धीमा किया जा सके, जैसे:

void loop(){
    Serial.write(analogRead(A0)/4);
    delay(50);
}

जहां तक ​​मुझे पता है, प्रोसेसिंग का उद्देश्य एक सुसंगत फ्रैमरेट पर चलना है, जिसे आप frameRate()फ़ंक्शन का उपयोग करके संशोधित कर सकते हैं । डिफ़ॉल्ट रूप से, यह 60 फ्रेम प्रति सेकंड है, हालांकि यह पुराने सिस्टम पर धीमी गति से चल सकता है (या जहां आप एक गहन कार्यक्रम चला रहे हैं)। आप यह पढ़ सकते हैं कि frameRateचर को पढ़कर यह कितनी तेजी से चल रहा है ।

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

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


14

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

दर्ज करें SerialEvent()

जैसा कि loop()आपके Arduino पर और draw()प्रसंस्करण में विरोध किया गया serialEvent()था, सीरियल बफर में कुछ नया होने पर ही सब कुछ अंदर होता है। इसलिए प्रसंस्करण के बजाय सवाल जितना संभव हो उतना तेज़ी से पूछें और आपका Arduino बहुत तेज़ी से वापस चिल्लाता है, उनके पास एक अच्छा, विनम्र (अतुल्यकालिक) वार्तालाप हो सकता है।

प्रसंस्करण और Arduino दोनों में एक धारावाहिक है। यह Arduino पर serialEvent () है और यह प्रसंस्करण में serialEvent () है। दोनों पक्षों पर क्रम का उपयोग करना, यह वही होगा जो होगा:

  1. प्रसंस्करण सीरियल कनेक्शन के लिए एक चरित्र भेजता है। यह कोई भी चरित्र हो सकता है, लेकिन अगर हम पूर्व निर्धारित करते हैं तो हम किसी भी अवांछित अनुरोध को फ़िल्टर कर सकते हैं जैसे कि एक शोर संकेत। इस उदाहरण के लिए, आइए Vहर बार भेजें कि हमें आपके पॉटमीटर की एक नई रीडिंग चाहिए। चरित्र भेजे जाने के बाद, हम हमेशा की तरह अपना व्यवसाय जारी रखते हैं। यहाँ एक उत्तर की प्रतीक्षा नहीं!

  2. Arduino की तरफ कुछ भी नहीं हो रहा है, जब तक कि यह सीरियल बफर में डेटा प्राप्त नहीं करता है। यह जाँच करता है कि आने वाला चरित्र एक है V, और हमें भाग्यशाली है, यह है। Arduino एक बार पॉटमीटर के मूल्य को पढ़ता है, उस मान को एक बार सीरियल में आउटपुट करता है, और ठंडा करने के लिए अधिकतम वापस जाता है। Protip: एक चरित्र के साथ मूल्य को समाप्त करें ( *हमारे मामले में)। इससे आपको अगले चरण में मदद मिलेगी।

  3. जब सीरियल सीरियल बफ़र में नए डेटा को बल में कोई गड़बड़ी होती है, तो प्रोसेसिंग अपना नियमित रूप से फ़ोटोग्राफ़ी पिक्सेल व्यवसाय कर रही है । यह तब तक स्विच करता है serialEvent(), और सीरियल डेटा पढ़ना शुरू करता है, जब तक कि हमारा समापन नहीं हो *जाता। यह जानने के लिए कि यह पढ़ने लायक अंतिम पात्र था, अब हम आने वाले मूल्य को एक ऐसे वेरिएबल में स्टोर कर सकते हैं, जो Arduino के रीडिंग को संग्रहीत करता है।

  4. बस। प्रसंस्करण अब नए सेंसर मूल्य को जानता है और जो कुछ भी हम इसे करने के लिए कहते हैं उसके साथ किया जाता है। इस बीच, आपका Arduino मौसम का आनंद ले रहा है या आने वाले सीरियल डेटा तक इसके अस्तित्व पर विचार कर रहा है।


1
और जब आप इस पर हों, तो अपने पॉटमीटर के समानांतर एक संधारित्र लगाएं। यह आपके DAC के इनपुट में थोड़े से बदलाव को सुचारू करता है, संभवतः प्रसंस्करण में घबराने वाली गति को रोकता है।
टॉम

इस अच्छे (और थोड़े एंथ्रोपोमोर्फिक) उत्तर के लिए धन्यवाद!
Zeta.Investigator

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

7

आपका मतदान पाश आपके प्रोसेसर की पूरी गति से चलता है, और प्रत्येक दौर में सीरियल पोर्ट को लिखता है।

इस तरह, आप सीरियल पोर्ट की तुलना में अधिक बार रास्ता लिख ​​सकते हैं क्योंकि यह संभाल सकता है।

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

यहां जो महत्वपूर्ण है वह यह है कि यह मूल्यों के क्रम को बनाए रखेगा: यह एक फीफो बफर है , जो फर्स्ट इन / फर्स्ट आउट ऑर्डर में काम कर रहा है।

क्या होता है:
लूप पोर्ट बफर को भरता है, और इसे 100% पूर्ण रखता है।
यदि आप पोटेंशियोमीटर को बदलते हैं, तो परिवर्तित मूल्य बफर के अंत में लिखा जाता है , पोर्ट तेजी से काम करता है क्योंकि यह बफर में सभी तत्वों को लिख सकता है, जो अभी भी पुराना मूल्य है।

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

अधिकतम आवृत्ति जो आपके डेटा को पढ़ने के लिए समझ में आती है, वह आवृत्ति है जिसे आप इसे लिख सकते हैं, इसलिए आपको कम से कम एक विलंब का उपयोग करना चाहिए जो कि वर्तमान पोर्ट गति पर बाइट्स को लिखने के लिए पर्याप्त लंबा है।


सामान्य रूप से इस तरह की देरी को रोकने के लिए एक और स्वतंत्र उपाय के रूप में,
आप इसके अतिरिक्त पोर्ट के लेखन बफ़र को न्यूनतम पर सेट कर सकते हैं।

इससे बहुत पहले बफ़र करने के बजाय डेटा को बहुत पहले छोड़ दिया जाएगा।

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


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

6

लगातार सीरियल डेटा भेजने के बजाय, केवल तभी डेटा भेजें, जब पोटेंशियोमीटर का मूल्य एक निश्चित सीमा से अधिक बदल गया हो।

int oldValue = 0;
const int threshold = 5;

void setup()
{
  Serial.begin(9600);
  pinMode(A0, INPUT)
}

void loop()
{
  if(oldValue >= analogRead(A0)+threshold || oldValue <= analogRead(A0)-threshold)
  {
    Serial.println(analogRead(A0));
    oldValue = analogRead(A0);
  }
}

1
यह loop()आउटपुट बफर को समान नमूनों के साथ नहीं भर रहा है, यह अच्छा है। लेकिन यह अभी भी प्रोसेसर की पूरी गति से चलता है, जो कि जितनी जल्दी हो सके 100 गुना तेज हो सकता है। इसका मतलब है कि यह अभी भी सीमा को जल्दी से सीमा तक भर सकता है यदि इनपुट बार-बार बदलता है, जैसे कि ऊपर के शोर से threshold, या उच्च रिज़ॉल्यूशन में एक निरंतर परिवर्तन (जो कि यहां उदाहरण के मामले में मामला नहीं है)
वोल्कर सिएगल

0

दो सरल समाधान जो अभी भी देख रहे हैं, उनके लिए काम करने की गारंटी है: -

  1. देरी को 50 से 100 मिलीसेकंड तक बढ़ाएं।

  2. के बाद इस जोड़े Serial.begin(9600)में setup();

    Serial.setTimeout(50);

चरण दो सबसे महत्वपूर्ण है। उपरोक्त कोड जोड़ने के बाद ही इसने मेरे लिए काम किया। यह कई अन्य मंचों में बहुत बार उल्लेख नहीं किया गया है जो मैंने देखा है जब मुझे सटीक समान समस्या थी।


यह कुछ हद तक गलत है। सेटटाइमआउट () विधि इनपुट पर लागू होती है, आउटपुट पर नहीं - इस दस्तावेज को arduino.cc/en/Serial/SetTimeout
क्रिस स्ट्रैटन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.