शून्य लूप के बाहर कार्य कैसे करते हैं?


9

मुझे Arduino स्केच का उपयोग एक void setup()भाग के साथ किया जाता है जो एक बार चलता है, और एक void loop()हिस्सा जो लूप करता रहता है। क्या होता है जब आपके पास मुख्य के बाहर शून्य कार्य होते हैं void loop()? क्या ये सभी समानांतर चल रहे हैं या वे एक के बाद एक चला रहे हैं? या कुछ शून्य कार्य केवल तभी चलते हैं जब कुछ मानदंड पूरे हो गए हों (जैसे कि कुछ समय बाद लूप)?

उदाहरण के लिए नीचे दिए गए कोड में, कार्य void receiveData(int byteCount)और void sendData()कार्य कब चलेंगे?

//I2C_test

//This code demonstrates communication via an I2C bus between a raspberry pi and an arduino.
//When the Raspberry pi (master) sends data to the Arduino (slave), the Arduino uses this
//data to control a motor. After the Arduino has recieved data from the master, it then collects
//data from the external environment via a sensor and sends this data back to the Raspberry pi.

#include <Wire.h>
int number = 0; //Declare variables
int val = 0;

void setup() {
  //Anything between the curly brackets runs once when the arduino is turned on or reset
  pinMode(0, INPUT);
  //Set pin 0 as input and 3 as output
  pinMode(3, OUTPUT);
  Serial.begin(9600);
  //Set the data rate for serial transmission at 9600bps
  Wire.begin(0x04);
  //Initiate the Wire library, join the Arduino as a slave, and specify its 7 bit slave address
  Wire.onReceive(receiveData);
  //Define callbacks for i2c communication
  Wire.onRequest(sendData);
}

void loop() {
  //The code between the curly brackets keeps repeating
  delay(100);
}

void receiveData(int byteCount) {
  while(Wire.available()) {
    number = Wire.read();
    //Set the variable "number" to the data sent by the master
    analogWrite(3, number);
    //Write this number to pin 3 (PWM). This controls the motor speed
  }
  val = analogRead(0);
  //Read the voltage on pin 0 (connected to the sensor). Map input voltages between 0 and 5 volts into integer values between 0 and 1023
}

void sendData() {
  Wire.write(val);
  //Send the data read from the sensor to the master.
}

यह दिलचस्प लग रहा है। मुझे आश्चर्य है कि यदि आप कोड के स्रोत से लिंक पोस्ट कर सकते हैं (और Arduino और Pi के बीच कनेक्शन का विवरण)।
मिलिवर्स

1
@Milliways मैंने Arduino uno और Raspberry pi (B + मॉडल) पर कोड लिखने के लिए इस * ट्यूटोरियल का उपयोग किया , हालांकि मैंने कुछ छोटे बदलाव किए। एसडीए और एससीएल पिंस को दो बोर्ड, साथ ही साथ ग्राउंड पिंस को हटा दें। विभिन्न बिजली आपूर्ति से जुड़े हैं। मैं तो एक संभावित विभक्त विन्यास में विन्यस्त सेंसर से जुड़ा पिन 3, + 5 वी और गैंड पिन के बीच जुड़ा था। पिन 0 और Gnd एक मोटर ड्राइव बोर्ड से जुड़ा है।
ब्लू 7

जवाबों:


11

setup()और loop()कार्यों असामान्य क्योंकि वे Arduino कोड द्वारा आप के लिए स्वचालित रूप से कहा जाता है। कोई अन्य कार्य इस तरह से व्यवहार नहीं करता है।

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

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

आपके द्वारा पोस्ट किया गया उदाहरण कोड काफी दिलचस्प है। इन पंक्तियों को देखें setup():

Wire.onReceive(receiveData);
Wire.onRequest(sendData);

ये लाइनें Wireकॉल करने के लिए ऑब्जेक्ट receiveData()और sendData()I2C घटनाओं के जवाब में बता रही हैं । यह फ़ंक्शन पॉइंटर्स को पारित करके ऐसा करता है जो संग्रहीत और उपयोग किया जाता है Wire

यदि आप इस बारे में अधिक जानना चाहते हैं तो मैं ऑनलाइन C / C ++ फंक्शन पॉइंटर्स के बारे में जानकारी खोजने की सलाह दूंगा । आपको Arduino के attachInterrupt()फ़ंक्शन का पता लगाने में भी रुचि हो सकती है।


आपके उत्तर के लिए धन्यवाद। यह अब अधिक समझ में आने लगा है। हालाँकि, जब तक उन्हें बुलाया नहीं जाता है, तब तक फ़ंक्शन receiveData()और sendData()फ़ंक्शन नहीं चलते हैं, तो उन्हें void setup()फ़ंक्शन के भीतर क्यों बुलाया जाता है और मुख्य void loop()फ़ंक्शन नहीं? निश्चित रूप से इन कार्यों को कभी नहीं बुलाया जाएगा जब तक कि दुर्लभ मौका नहीं है कि एक i2c घटना है जबकि अनुदेश सूचक अभी भी void setupफ़ंक्शन के भीतर है ? क्या फ़ंक्शन के भीतर से इन फ़ंक्शन को कॉल करना बेहतर नहीं होगा void loopताकि जब भी कोई i2c इवेंट हो, तो फ़ंक्शन कहा जाता है?
ब्लू 7

4
@ ब्लू 7 इन कार्यों को नहीं कहा जाता है void setup(), वे के पैरामीटर के रूप में पारित किए जाते हैं onReceiveऔर onRequest, वे टिप्पणी के रूप में कॉलबैक होते हैं । बहुत ही कम सारांश में: यह जब विशिष्ट बातें होती हैं (इन कार्यों कॉल करने के लिए तार पुस्तकालय (से कोड) कहता है arduino.cc/en/Reference/WireOnReceive , arduino.cc/en/Reference/WireOnRequest ...)
FredP

@FredP आह ठीक है। लिंक के लिए धन्यवाद, जब मैं अपने फ़ोन पर नहीं होता, तो मैं उन्हें देख लेता हूँ। मेरे पास इस बीच एक त्वरित प्रश्न है, यदि आप बुरा नहीं मानते हैं। क्या ये कॉलबैक हमेशा तैयार हैं और i2c इवेंट का इंतजार कर रहे हैं? यानी, कोई फर्क नहीं पड़ता कि अनुदेश सूचक कहां है, ये कॉलबैक तुरंत i2c इवेंट होते ही फ़ंक्शन को कॉल करेंगे?
ब्लू 7

1
@ Blue7 संभवतः I2C गतिविधि की निगरानी के लिए इंटरप्ट का उपयोग कर रहा है। जब कोई व्यवधान निष्पादित होता है, तो यह अस्थायी रूप से मुख्य कार्यक्रम से दूर हो जाता है।
पीटर ब्लूमफील्ड

3
@ Blue7 कॉलबैक प्रतीक्षा नहीं कर रहे हैं (Arduino मल्टीट्र्रेड नहीं है), जैसा कि @PeterRBloomfield कहता है, वायर लाइब्रेरी I2C को twi_init()तब सक्षम करती है जब आप कॉल करते हैं Wire.begin। जब I2C गतिविधि होती है, तो doingC अपने वर्तमान कार्य को करना बंद कर देता है (जब तक ... इस समय के लिए कोई बात नहीं है :-) और वायर लाइब्रेरी के कोड में जाता है, तब तब कॉल करना उचित होगा (जो हो रहा है, उसके आधार पर) आप के रूप में पंजीकृत है। कॉलबैक ( receiveDataउदाहरण के लिए)। एक कॉलबैक जैसे कार्यों के लिए सामान्य नाम है receiveDataया sendDataवे एक से बुलाया कर रहे हैं, बाधा हैंडलर तार के अंदर।
फ्रेड पीपी

2

क्या यह ऐसा मामला नहीं setup()है जिसे एक बार बुलाया जाता है और loop()बार-बार बुलाया जाता है? अर्थात एक अनदेखी है main() जो इस तरह दिख सकती है:

void main(){
  setup();
  while(True){
    loop();
  }
}

माफी के रूप में मैं सिर्फ Arduino में देख रहा हूँ और लगभग कोई C / C ++ अनुभव नहीं है; मैं loop()खुद इस स्थिति को संभालने की कोशिश कर रहा हूं।


असल में, हाँ। एक ऐसी कॉल भी है init()जिसके लिए टाइमर्स जा रहा है millis, delayआदि तो init()सामान्य इनिशियलाइज़ेशन के setup()लिए है, आपके इनिशियलाइज़ेशन के लिए है, और loopइसके लिए, अच्छी तरह से, लूपिंग है। आप अपना खुद का लिख ​​सकते हैं mainयदि आप पूर्ण नियंत्रण लेना चाहते हैं।
निक गैमन

अच्छा लेख। बीटीडब्ल्यू ;की आवश्यकता नहीं है के बाद }
प्रायद्वीप

Serial_event की कॉल भी है () क्या यह नहीं है?
दिविसाडेरो

2

मैं डी की प्रतिक्रिया पर टिप्पणी नहीं कर सकता। मुख्य लूप में निष्पादित वास्तविक कोड यहाँ है :

    int main(void) {
    init();
    initVariant();

    setup();

    for (;;) {
        loop();
        if (serialEventRun) serialEventRun();
    }   
    return 0;
}

और हाँ, setup()एक बार कॉल loop()किया जाता है और बार-बार बुलाया जा रहा है (कुछ सीरियल सामान के साथ)।


0

यह सामान्य कार्य के रूप में काम करता है, इसे समझ बनाने के लिए बुलाया जाना चाहिए। लूप () / सेटअप () को एक मुख्य () फ़ंक्शन से बुलाया जाता है जिसे Arduino निर्देशिका से संकलित किया जाता है और इसमें लिंक किया जाता है। ReceData / sendData को आपके प्रोग्राम से कॉल किया जाता है जो रूट लूप / सेटअप फ़ंक्शन में है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.