কোনও ইনপুট পরিবর্তিত হলে কোনও ফাংশন স্বয়ংক্রিয়ভাবে বলা যেতে পারে?


21

বর্তমানে, আমার স্কেচটি প্রতিটি লুপের চারপাশে একটি ইনপুট পিন চেক করছে। যদি এটি কোনও পরিবর্তন সনাক্ত করে, এটির প্রতিক্রিয়া জানাতে এটি একটি কাস্টম ফাংশনকে কল করে। এখানে কোড (প্রয়োজনীয়গুলি ছাঁটাই):

int pinValue = LOW;

void pinChanged()
{
    //...
}

void setup()
{
    pinMode(2, INPUT);
}

void loop()
{
    // Read current input
    int newValue = digitalRead(2);

    // Has the input changed?
    if (newValue != pinValue) {
        pinValue = newValue;
        pinChanged();
    }
}

দুর্ভাগ্যক্রমে, ইনপুটটিতে খুব স্বল্প পরিবর্তনের জন্য এটি সর্বদা সঠিকভাবে কাজ করে না (যেমন সংক্ষিপ্ত ডাল), বিশেষত যদি loop()কিছুটা ধীরে ধীরে চলতে থাকে।

আরডুইনোগুলি ইনপুট পরিবর্তনটি সনাক্ত করতে এবং আমার ফাংশনটি স্বয়ংক্রিয়ভাবে কল করার কোনও উপায় আছে?


1
আপনি এটির বাহ্যিক বাধা কী খুঁজছেন
বুটজেক

উত্তর:


26

আপনি এটি বাহ্যিক বাধা ব্যবহার করে করতে পারেন। বেশিরভাগ আরডুইনো যদিও সীমিত সংখ্যক পিনগুলিতে এটি সমর্থন করে। সম্পূর্ণ বিবরণের জন্য ডকুমেন্টেশনটি দেখুন attachInterrupt()

ধরে নিই যে আপনি একটি ইউনো ব্যবহার করছেন, আপনি এটি এটি করতে পারেন:

void pinChanged()
{
    //...
}

void setup()
{
    pinMode(2, INPUT);
    attachInterrupt(0, pinChanged, CHANGE);
}

void loop()
{
}

pinChanged()বাহ্যিক বাধা 0 তে যখনই কোনও পরিবর্তন সনাক্ত হয় তখনই এটি কল করবে the ইউনোতে, এটি জিপিআইও পিনের সাথে সাদৃশ্যযুক্ত 2. অন্যান্য বোর্ডগুলিতে বাহ্যিক বিঘ্নিত নম্বর পৃথক, সুতরাং প্রাসঙ্গিক ডকুমেন্টেশন পরীক্ষা করা গুরুত্বপূর্ণ।

যদিও এই পদ্ধতির সীমাবদ্ধতা রয়েছে। কাস্টম pinChanged()ফাংশনটি একটি বিঘ্নিত পরিষেবা রুটিন (আইএসআর) হিসাবে ব্যবহৃত হচ্ছে। তার মানে loop()কলটি কার্যকর হওয়ার সময় বাকি কোড (সমস্ত কিছু ) অস্থায়ীভাবে বন্ধ হয়ে যায়। কোনও গুরুত্বপূর্ণ সময় বাধাদান রোধ করার জন্য, আপনার লক্ষ্য হওয়া উচিত যত দ্রুত সম্ভব আইএসআর করা।

আপনার আইএসআর চলাকালীন অন্য কোনও বাধা চলবে না তাও লক্ষ করা গুরুত্বপূর্ণ। এর অর্থ হ'ল বিঘ্নের উপর নির্ভর করে এমন কোনও কিছু (যেমন কোর delay()এবং millis()ফাংশন) এর অভ্যন্তরে সঠিকভাবে কাজ না করে।

সবশেষে, যদি আপনার আইএসআর স্কেচে কোনও গ্লোবাল ভেরিয়েবল পরিবর্তন করতে হয় তবে সেগুলি সাধারণত হিসাবে ঘোষণা করা উচিত volatile, যেমন:

volatile int someNumber;

এটি গুরুত্বপূর্ণ কারণ এটি সংকলককে বলে যে মানটি অপ্রত্যাশিতভাবে পরিবর্তিত হতে পারে, সুতরাং এটির কোনও পুরানো কপি / ক্যাশে ব্যবহার না করা সতর্ক হওয়া উচিত।


প্রশ্নে উল্লিখিত "সংক্ষিপ্ত ডালগুলি" সম্পর্কে, পিনটি বাধাগ্রস্ত করতে ট্রিগার করার জন্য একটি রাষ্ট্রের সর্বনিম্ন সময় থাকতে হবে? (স্পষ্টত এটি পোলিংয়ের চেয়ে অনেক কম হবে, যা লুপে কী ঘটছে তার উপর নির্ভর করে)
স্যাচলীন

1
@ সাচলিন এটি যতক্ষণ কাজ করবে যতক্ষণ না এটি আইএসআর কার্য সম্পাদনের সময় ঘটে না (উত্তরে বর্ণিত হয়েছে); সে কারণেই pinChanged()যতটা সম্ভব সংক্ষিপ্ত হওয়া উচিত। সুতরাং সাধারণত ন্যূনতম সময়টি সময়টি pinChanged()নিজেই সঞ্চালনের সময় হওয়া উচিত ।
jfpoil ব্যাখ্যা

2
এই অতি উত্তরের উত্তরের জন্য +1 এর মধ্যে অন্তর্ভুক্তি ব্যবহার করার সময় সমস্ত অবাস্তব জিনিসপত্রের যত্ন নেওয়া উচিত!
jfpoil ব্যাখ্যা

3
ভাগ করা গ্লোবালগুলি ঘোষণার পাশাপাশি volatile, বৈশ্বিক চলকটি যদি 1 বাইটের চেয়ে বেশি বিস্তৃত হয় তবে কিছুসংখ্যার হিসাবে, আপনাকে অবশ্যই প্রোগ্রাম দ্বারা বাইট অ্যাক্সেসের মধ্যে ঘটে যাওয়া পিন-পরিবর্তন বাধা থেকে রক্ষা করতে হবে। একটি বিবৃতিতে someNumber +=5;লো বাইট যুক্ত করা এবং ক্যারি অন্তর্ভুক্ত সহ উচ্চ বাইট যুক্ত করা জড়িত। এই দুটি (আরও, বৃহত্তর ভেরিয়েবলের জন্য) অবশ্যই কোনও বাধা দ্বারা ভাগ করা উচিত নয়। অপারেশনগুলি বন্ধ করে দেওয়া এবং অপারেশনের আগে ও পরে যথাক্রমে পুনরুদ্ধার করা (যথাক্রমে) যথেষ্ট।
জে রবার্ট

@ সাচলিন - সর্বনিম্ন ডাল আকার সম্পর্কে। ডেটাশিটে একটি নির্দিষ্ট উত্তর খুঁজে পাওয়া শক্ত, তবে পিন-চেঞ্জের বিঘ্নগুলির জন্য সময় বিবেচনা করে সেগুলি আধা ঘন্টার চক্রের মধ্যে ল্যাচ করা হয়। একবার বাধা "স্মরণ" হয়ে গেলে এটি আইএসআর লাথি না মেরে এবং এর সাথে ডিল না হওয়া অবধি স্মরণে থেকে যায়।
নিক গ্যামন

5

ডিজিটাল ইনপুট হিসাবে কনফিগার করা যে কোনও পিনের যে কোনও পরিবর্তনের পরিস্থিতি একটি বাধা তৈরি করতে পারে। আইএনটি 1 বা আইএনটি 2 দ্বারা বিঘ্নিত কারণগুলির জন্য অনন্য ভেক্টরগুলির বিপরীতে পিনচঞ্জেইন্ট বৈশিষ্ট্যটি একটি সাধারণ ভেক্টর ব্যবহার করে এবং তারপরে ইন্টারপ্রেট সার্ভিস রুটিন (ওরফে আইএসআর) এরপরে কোন পিনটি পরিবর্তন হয়েছে তা নির্ধারণ করতে হবে।

ভাগ্যক্রমে পিনচেনজিট লাইব্রেরি এটিকে সহজ করে তোলে।

PCintPort::attachInterrupt(PIN, burpcount,RISING); // attach a PinChange Interrupt to our pin on the rising edge
// (RISING, FALLING and CHANGE all work with this library)
// and execute the function burpcount when that pin changes

0

আপনি কেবলমাত্র উচ্চ বা নিম্নগর্ভের চেয়ে কোনও প্রান্তিক দ্বার পার হয়ে কোনও ভোল্টেজ সনাক্ত করতে চান এমন ইভেন্টে আপনি অ্যানালগ তুলকটি ব্যবহার করতে পারেন। উদাহরণস্বরূপ স্কেচ:

volatile boolean triggered;

ISR (ANALOG_COMP_vect)
  {
  triggered = true;
  }

void setup ()
  {
  Serial.begin (115200);
  Serial.println ("Started.");
  ADCSRB = 0;           // (Disable) ACME: Analog Comparator Multiplexer Enable
  ACSR =  bit (ACI)     // (Clear) Analog Comparator Interrupt Flag
        | bit (ACIE)    // Analog Comparator Interrupt Enable
        | bit (ACIS1);  // ACIS1, ACIS0: Analog Comparator Interrupt Mode Select (trigger on falling edge)
   }  // end of setup

void loop ()
  {
  if (triggered)
    {
    Serial.println ("Triggered!"); 
    triggered = false;
    }

  }  // end of loop

এটি লাইট-ডিটেক্টরগুলির মতো জিনিসগুলির জন্য দরকারী হতে পারে, যেখানে আপনাকে একটি ইনপুটটিতে 1V থেকে 2V থেকে পরিবর্তন (বলুন) পরিবর্তন সনাক্ত করতে পারে।

সার্কিট উদাহরণ:

এখানে চিত্র বর্ণনা লিখুন

আপনি প্রসেসরে ইনপুট ক্যাপচার ইউনিটও ব্যবহার করতে পারেন যা টাইমার / কাউন্টারের বর্তমান গণনা 1 সংরক্ষণ করে নির্দিষ্ট ইনপুটগুলির সঠিক সময়টি মনে রাখবে This এটি আপনাকে সঠিক (ভাল, প্রায় সঠিক) মুহুর্তটি সংরক্ষণ করতে দেয় বর্তমান সময় ক্যাপচার করার জন্য কোনও আইএসআর ব্যবহার করার আগে বিলম্বের (সম্ভবত কয়েকটি মাইক্রোসেকেন্ডের) পরিচয় দেওয়ার পরিবর্তে আগ্রহ দেখা দিয়েছে।

সময়-সমালোচনামূলক অ্যাপ্লিকেশনগুলির জন্য, এটি কিছুটা বর্ধিত নির্ভুলতা দিতে পারে।

উদাহরণ অ্যাপ্লিকেশন: আপনার আরডুইনোকে ক্যাপাসিটার পরীক্ষক হিসাবে পরিণত করুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.