اجرای یک دستور در فواصل زمانی مشخص در آردینو

1 سال قبل
332 بازدید

0

سلام. آیا این امکان وجود دارد که در آردینو یک دستور را به صورت خودکار مثلا هر ۶ ساعت یکبار اجرا کرد؟ اگر امکان داره لطفا دستوراتش رو بفرمایید.

از چند نفر پرسیدم گفتن این امکان وجود نداره و در سایر بخشهای برنامه ایجاد مشکل میکنه.

12 شهریور 02 در 09:58
راحله
1

افزودن دیدگاه

6 پاسخ ثبت شده است
0

با سلام.

اگر مصرف برق برای کاربرد شما اهمیت دارد، می توانید از ESP8266 یا ESP32 استفاده کنید و آن را به مدت دلخواه خود به حالت Sleep ببرید تا وقتی که از این حالت خارج شد، دستورات شما را اجرا کنید. حدوداً تا 1 ساعت می تواند به حالت sleep برود. هر ساعت یکبار که از این حالت خارج شد، به یک شمارنده، 1 عدد اضافه کنید و وقتی شماره شما برابر 6 شد، کد مشخص خود را اجرا کنید.

اگر این موضوع اهمیت ندارد، می توانید از بردهای آردوینو به همراه ماژولهای تایمر و ساعت استفاده کنید. هر لحظه ساعت را چک کنید و پس از گذشت مدت دلخواه، کد خود را اجرا کنید.

اگر ماژولی را پیدا کنید که خروجی وقفه (Interrupt) داشته باشد، نیاز به چک کردن ساعت وجود نخواهید داشت و فقط در تابع وقفه، کد مورد نظر خود را بنویسید.

12 شهریور 02 در 10:15
مجید مرآتی
609

بله میخوام از آردینو استفاده کنم، لطفا یک ماژول تایمر برای این منظور معرفی بفرمایید  – راحله 02-06-12 در 10:17

فعلا در فروشگاه، این نمونه از ماژول ساعت و تاریخ موجود است. https://thecaferobot.com/store/clock-time-ds1307-i2c-rtc  – مجید مرآتی 02-06-12 در 10:23

ممنون با این ماژول میتوانم کاری کنم که یکی‌از پایه های آردینو در زمان مشخص ۵ ولت یا صفر شود؟  – راحله 02-06-12 در 10:26

بله. فقط کافیست یاد بگیرید که زمان را از روی آن بخوانید  – مجید مرآتی 02-06-12 در 12:28

افزودن دیدگاه

0

بله، می‌توانید در آردوینو یک دستور را به صورت خودکار و با فاصله زمانی مشخص اجرا کنید. برای این کار می‌توانید از تایمرها و توابع زمان‌سنجی در آردوینو استفاده کنید.

 

یک راه بسیار ساده برای اجرای یک دستور هر 6 ساعت، استفاده از توابع `millis()` و متغیرهای زمانی است. متغیرهای زمانی به شما اجازه می‌دهند زمان گذشته شده را بر اساس مقدار بازگشتی `millis()` محاسبه کنید.

 

در زیر یک نمونه کد آردوینو برای اجرای یک دستور هر 6 ساعت آورده شده است:

 

unsigned long previousMillis = 0; // متغیری برای ذخیره زمان سپری شده

// 6 * 60 * 60 * 1000 = 21600000 // محاسبه مدت زمان مورد نظر  بر حسب میلی‌ثانیه (6 ساعت در مورد سوال شما برحسب میلی ثانیه محاسبه شده)
const unsigned long interval = 21600000; 

void setup()
{
  // کد مربوط به تنظیمات اولیه
}

void loop() {
  unsigned long currentMillis = millis(); // زمان فعلی را دریافت می‌کنیم 

  if (currentMillis - previousMillis >= interval)    // مدت زمان سپری شده را بررسی می‌کنیم 
  {
    previousMillis = currentMillis; // زمان سپری شده را به روز می‌کنیم 

    // دستور مورد نظر اجرا شود

    // این قسمت را با دستور مورد نظر خود جایگزین کنید

    // مثال: digitalWrite(13, HIGH);
  }

  // کد بقیه برنامه

}

 

در این کد، متغیر `previousMillis` برای ذخیره زمان گذشته شده استفاده می‌شود. هر بار که زمان گذشته شده از فاصله زمانی تعیین شده (`interval`) بیشتر یا مساوی شود، دستور مورد نظر در قسمت مشخص شده اجرا می‌شود و متغیر `previousMillis` به روز رسانی می‌شود.

در این نمونه، فاصله زمانی 6 ساعت را با استفاده از ضرب در 60 (دقیقه) و 60 (ثانیه) و 1000 (میلی‌ثانیه) به میلی‌ثانیه تعیین کرده‌ایم. شما می‌توانید این مقدار را به طور مستقیم تغییر دهید تا فاصله زمانی مورد نظر خود را تنظیم کنید.

لازم به ذکر است که اگر در طول اجرای دستورات دیگری نیاز به استفاده از توابع `delay()` داشته باشید، بهتر است از توابع غیرمسدودکننده مانند `millis()` و `micros()` استفاده کنید.

15 شهریور 02 در 07:39
حسین میرزاپور
111

ممنون خیلی عالی بود، فقط یک سوال این دستورات در دراز مدت که. مثلا هر ۶ ساعت قرار هست یک دستور مشخص را اجرا کند در عملکرد سایر دستورات برنامه اخلالی ایجاد نمیکند؟ یا باعث هنگ کردن میکرو نمیشد؟؟  – راحله 02-06-18 در 11:18

خیر مشکلی ایجاد نمی‌کند چون در هر بار اجرای حلقه loop با دستور if چک می‌کنیم که زمان مورد نظر فرا رسیده یا خیر در غیر اینصورت سایر دستورات را اجرا می کند. از این نظر بر خلاف دستور delay هیچ اخلالی در برنامه ایجاد نمیکنه. برای مطالعه بیشتر در این مورد میتونید کد چراغ چشمک زن بدون استفاده از دستور delay رو در خود نمونه کدهای ide آردوینو بررسی بفرمایید و تجربه کنید. این دو لینک هم در همین مورد مفصل با تصویر و نمونه کد، توضیح دادند: https://linuxhint.com/blink-without-delay-arduino/ و این لینک: https://arduino.ir/Tutorial/BlinkWithoutDelay تنها نکته ای که باید به آن توجه شود این است که تابع millis حدوداً هر 49 روز سرریز شده (یعنی مقدارش صفر میشه) و شمارش رو از اول شروع میکنه که با در نظر گرفتن این نکته در برنامه میتونید تمهیدات لازم رو در برنامه تدارک ببینید.  – حسین میرزاپور 02-06-18 در 02:27

در مورد هنگ کردن میکرو هم نگرانی وجود نداره اما برای اطمینان در تمامی پروژه‌هایی که حساسیت و دقت در انجام حتمی دستورات مد نظر باشه میتونید از تایمر watchdog یا سگ نگهبان در آردوبنو استفاده کنید که برنامه رو تحت نظر میگیره و در صورت بروز هر ایراد و اجرا نشدن دستورات و هنگ کردن میکرو ، watchdog میکرو را ریست کرده و برنامه رو خط به خط از اول اجرا میکنه.  – حسین میرزاپور 02-06-18 در 02:30

لینک های زیر نمونه برنامه و طرز کار تایمر watchdog رو به خوبی توضیح و آموزش داده: https://melec.ir/watchdog-in-arduino/ https://digispark.ir/setup-arduino-watchdog-timer/h https://www.electronicwings.com/arduino/watchdog-in-arduino اکر از بوردهای آردوینو مبتنی بر ESP32 استفاده می کنید از این کتابخانه و نمونه کد برنامه استفاده کنید: https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/Timer/WatchdogTimer/WatchdogTimer.ino  – حسین میرزاپور 02-06-18 در 03:14

خیلی سپاسگزارم، ببخشید در این حالت وقتی تایمر بعد از ۴۹ روز سرریز میکنه چه اتفاقی میافته؟ مجددا به صورت خودکار از صفر شروع میکنه به شمارش و در فواصل زمانی تعیین شده دستور مورد نظر احرا میکنه یا بعد از سرریز دستوراتی که قرار هست در فواصل زمانی مشخص شده اجرا شود متوقف می شود و تا ریست میکرو دیگر اجرا نمیشوند؟  – راحله 02-06-18 در 03:43

افزودن دیدگاه

0

خواهش می کنم.

ببینید وقتی millis بعد از 49 روز یا اگر دقیقش رو بخواهیم بگیم و  ۴۹.۷۱ روز (به عبارت دقیق تر  هر  ۲ به توان ۳۲ میلی ثانیه) - یعنی حدوداً  نزدیک به 50 روز - سر ریز میشه یعنی مقدار millis  صفر میشه.

unsigned long previousMillis = 0; // متغیری برای ذخیره زمان سپری شده

 // محاسبه مدت زمان مورد نظر  بر حسب میلی‌ثانیه (6 ساعت در مورد سوال شما برحسب میلی ثانیه محاسبه شده):
const unsigned long interval =21600000;  // 6 * 60 * 60 * 1000;

void setup()
{
  // کد مربوط به تنظیمات اولیه
}

void loop() 
{
  unsigned long currentMillis = millis(); // زمان فعلی را دریافت می‌کنیم. این عدد هر 50 روز دوباره صفر میشه


  if (currentMillis - previousMillis >= interval)   // مدت زمان سپری شده را بررسی می‌کنیم 
  { 
    previousMillis = currentMillis; // زمان سپری شده را به روز می‌کنیم 

    // دستور مورد نظر اجرا شود

    // این قسمت را با دستور مورد نظر خود جایگزین کنید

    // مثال: digitalWrite(13, HIGH);

  } 

  // کد بقیه برنامه

}
18 شهریور 02 در 07:39
حسین میرزاپور
111

ممنون ممنون. یعنی با گذاشتن یک else بعد از ۴۹ روز مجددا تایمر صفر میشه و تا ۴۹ روز‌آینده براساس زمان تعیین شده دستور مورد نظر اجرا میشه و این روند همینطور ادامه دارد و در روند برنامه خللی ایجاد نمیشود؟ و سوال دیگر اینکه در بین این ۴۹ روز مثلا روز بیست و پنجم اگر تغذیه آردینو را قطع و وصل کنیم تایمر صفر میشه و ۴۹ روز از لحظه روشن شدن محاسبه میشه یا تایمر در حافظه میماند؟  – راحله 02-06-18 در 08:51

بله همینطوره خللی ایجاد نمیشه، اگر مثلا روز بیست و پنجم هم برق قطع و وصل بشه یا تغذیه آردوینو را قطع و وصل کنیم تایمر از اول شمارش رو شروع میکنه و 49 روز از لحظه روشن شدن مجدد محاسبه میشه.  – حسین میرزاپور 02-06-19 در 08:39

ببخشید دستور else که فرمودید رو اضافه میکنم دیکه تایمر عمل نمیکنه و طبق زمان تعیین شده دستورات مورد نظر اجرا نمیشه!!  – راحله 02-06-19 در 08:55

نباید مشکلی ایجاد کنه. من برنامه رو تست میکنم اگر اشکالی دیدم اصلاح میکنم تا چند ساعت ان‌شاءالله دیگه اصلاح شده آپلود میکنم  – حسین میرزاپور 02-06-19 در 03:31

ممنونم  – راحله 02-06-19 در 06:46

افزودن دیدگاه

0

خوب من برنامه رو بدون else تست کردم و از اونجایی که نمیتونیم 50 روز صبر کنیم متغیرهای زمانی و شرایط سرریز شدن millis رو شبیه سازی کردم و متغیرهای زمان رو مانیتور کردم. خوشبختانه نیاز به قسمت else نداریم و برنامه بعد از سرریز هم درست به کارش ادامه میده . پس کد زیر بدون مشکل کار میکنه:

 

unsigned long previousMillis = 0; // متغیری برای ذخیره زمان سپری شده

 // محاسبه مدت زمان مورد نظر بر حسب میلی‌ثانیه (6 ساعت در مورد سوال شما برحسب میلی ثانیه محاسبه شده):
const unsigned long interval = 21600000; //6 * 60 * 60 * 1000;

void setup() 
{
  // کد مربوط به تنظیمات اولیه
}

void loop() 
{
  unsigned long currentMillis = millis(); // زمان فعلی را دریافت می‌کنیم. این عدد هر 50 روز دوباره صفر میشه

  if (currentMillis - previousMillis >= interval)   // مدت زمان سپری شده را بررسی می‌کنیم 
  { 
    previousMillis = currentMillis; // زمان سپری شده را به روز می‌کنیم 

    // دستور مورد نظر اجرا شود
    // این قسمت را با دستور مورد نظر خود جایگزین کنید
    // مثال: digitalWrite(13, HIGH);
  }
  // کد بقیه برنامه
}
19 شهریور 02 در 07:10
حسین میرزاپور
111

اگر خواستید خودتون هم تست کنید میتونید به جای millis در کد فوق برای تست نتیجه در زمان کوتاهتر از تابع micros استفاده کنید. سرریز این تابع حدود 70 دقیقه است من کد رو بر اساس این تابع تست کردم و زمان interval رو هم 5 دقیقه تنظیم کردم و الان هر 5 دقیقه اون قسمت برنامه داره اجرا میشه و بعد از 70 دقیقه هم مشکلی نداره و به کارش ادامه میده.  – حسین میرزاپور 02-06-19 در 07:15

نکته دیگه هم که قبلاً پرسیده بودید اینکه کدهایی که در قسمت مشخص شده که نوشتم «کد بقیه برنامه» بدون اینکه کاری با زمان مورد نظر شما داشته باشند بدون وقفه و مزاحمت کارشون رو ادامه میدن.  – حسین میرزاپور 02-06-19 در 07:19

متشکر، امتحان میکنم نتیجه رو خدمتتون عرض میکنم. یعنی من هم برای هر ۶ ساعت نیاز به else ندارم و بعد از پنجاه روز خودش صفر میشه؟  – راحله 02-06-19 در 07:19

اگر خواستید بفرمایید تا کد برنامه تستی رو هم که بر اساس micros تغییر دادم آپلود کنم تا خودتون نتیجه رو در 70 دقیقه ببینید  – حسین میرزاپور 02-06-19 در 07:21

ممنون میشم آپلود بفرمایید که تست کنم  – راحله 02-06-19 در 07:40

ببخشید من متوجه نشدم، شما فرمودید تست کردید و بدون else هم کار کرده و بعد از سرریز هم کار میکنه و نیاز به else نداره اما در دستوراتی که آپلود کردید else رو گذاشتید  – راحله 02-06-19 در 07:50

ببخشید اصلاح شد  – حسین میرزاپور 02-06-19 در 07:56

افزودن دیدگاه

0

 

به تفاوت اعداد مشخص شده دقت کنید. اینجا تابع micros سرریز شده و برنامه بدون هیچ اختلالی داره به کارش ادامه میده.

این هم کدی که برای تست تغییر دادم . سرریزش 70 دقیقه است:

یک LED به pin13 وصل کنید، پنجره serial رو باز کنید و برنامه رو اجرا کنید در ابتدا LED خاموشه ولی بعد از 5 دقیقه روشن شده و هر 5 دقیقه خاموش یا روشن میشه هربار به عدد counter در پنجره serial دقت کنید. تعداد دفعات اجرای برنامه مورد نظر رو نشون میده وقتی این عدد از 14 بیشتر شد یعنی تابع سرریز شده ولی برنامه بدون مشکل به کارش ادامه میده.

 

const int ledPin = LED_BUILTIN;  // the number of the LED pin:    پین 13

// Variables will change:
int ledState = LOW;  // ledState used to set the LED


unsigned long previousMillis = 0; // متغیری برای ذخیره زمان سپری شده
 // محاسبه مدت زمان مورد نظر  بر حسب میلی‌ثانیه (6 ساعت در مورد سوال شما برحسب میلی ثانیه محاسبه شده):
//  6 * 60 * 60 * 1000 =  21600000 
// حتما نتیجه ضرب بالا رو در متغیر ذخیره کنید مثل خط زیر:  
//const unsigned long interval =  21600000;

//test: ///////////////// محاسبه مدت زمان مورد نظر  بر حسب میکرو ثانیه (5 دقیقه برای تست بجای 6 ساعت برحسب میکرو ثانیه محاسبه شده):
const unsigned long interval =3000000; // 1000000 * 60 * 5 =   5 minuet       
////////////////////////
void setup() {
  // کد مربوط به تنظیمات اولیه
 Serial.begin(9600); 
 Serial.println("Start: ");
}

int counter = 0;
void loop() {
 //unsigned long currentMillis = millis(); // زمان فعلی را دریافت می‌کنیم. این عدد هر 50 روز دوباره صفر میشه

//test: ///////////////// این قسمت برای تست تغییر داده شده
// زمان فعلی را دریافت می‌کنیم. این عدد هر 70 دقیقه  صفر میشه 
unsigned long currentMillis = micros(); //  millis  برای تست به جای 
/////////////////////////
  // مدت زمان سپری شده را بررسی می‌کنیم 

  if (currentMillis - previousMillis >= interval)
  { 
   counter++;
   Serial.print(currentMillis - previousMillis);
   Serial.print("  currentMillis:    ");Serial.print(currentMillis); 
   Serial.print("   Prev: "); Serial.print(previousMillis); 
   Serial.print("   Counter: "); Serial.print(counter); Serial.println();
   
    previousMillis = currentMillis; // زمان سپری شده را به روز می‌کنیم 
  
  // دستور مورد نظر اجرا شود

    // این قسمت را با دستور مورد نظر خود جایگزین کنید

    // مثال: digitalWrite(13, HIGH);
        // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  } 

  // کد بقیه برنامه
  //   کدهایی که اینجا می نویسید بدون مزاحمت و بدون تاخیر، مستقلا اجرا میشن

}
19 شهریور 02 در 08:06
حسین میرزاپور
111

خیلی ممنون جناب میرزاپور که کمک میکنید. پس با این حساب دیگر نیازی به else نیست و بعد از سریز هم در فواصل در زمانی تعیین شده برنامه به کار خودش ادامه میده؟‌فقط ببخشید دلیل اینکه بعد از سرریز متوقف نمیشه چیه؟مگر مقدار منفی‌نمیشه و طبیعتا نباید ادامه بده و به دلیل برقرار نبودن شرط باید عمل نکنه، اما شما میفرمایید بعد از سرریز هم ادامه میده و دیگر به else یا برنامه دیگری هم نیاز نیست  – راحله 02-06-19 در 08:13

خواهش میکنم. بله من هم فکر میکردم عدد منفی میشه برای همین به اشتباه افتادم. اما با توجه به اینکه متغیر currentMillis و previusMillis از نوع unsigned هستند تفاضل اونها رو هم در قالب unsigned نشون میده و عدد منفی برنمیگردونه پس برنامه وارد شرط میشه. این رو با مانیتور کردن متغیرها متوجه شدم. بنابراین سرریز شدن رو مدیریت میکنه. اگر متغیر ها از نوع long بودند و unsigned نبودند حتما نتیجه تفاضل منفی می‌شد و دیگه وارد شرط نمی‌شد . این برنامه تست الان بعد از حدود 90 دقیقه که از اجراش میگذره با وجود اینکه تابع mircros سرریز شده همچنان درست کار میکنه و عدد counter هم به 16 رسیده تصویرش رو در کد بالا آپلود کردم  – حسین میرزاپور 02-06-19 در 08:24

خیلی ممنونم تست کردم و در سریال مانیتور عملکرد تایمر را مشاهده کردم، خیلی نکته مهمی را به من آموختید، باز هم سپاسگزارم. یک سوال دیگر در مورد اعتبار سیمکارت هم در انجمن مطرح کردم که اگر فرصت کردید ممنون میشم در اون زمینه هم کمکم کنید.  – راحله 02-06-20 در 09:10

سلام. خواهش میکنم خوشحالم تونستم کمک کنم. بله حتما نگاه میکنم اگر در توانم باشه و بتونم کمک کنم حتما پاسخ خواهم داد.  – حسین میرزاپور 02-06-20 در 09:34

ممنون  – راحله 02-06-20 در 10:20

سلام ببخشید جناب مهندس میرزاپور، با این روش میتونم چند دستور را در فواصل زمانی گوتاگون اجرا کنم؟ یا فقط یک مورد در یک فاصله ژمانی میشود؟ مثلا دستوری هر ۱۲ ساعت دستور دیگری هر ۶ ساعت و دستور دیکری هر ۳ ساعت؟؟  – راحله 02-12-01 در 07:10

سلام . بله قطعا یکی از مزایای این روش برنامه ریزی همزمان چند رویداد با فواصل زمانی متفاوت است. همانطور که میدانید این کار با دستور delay امکانپذیر نیست. نکته مهم این است که در فرایندهایی که با این روش برنامه ریزی میکنید از delay نباید استفاده کنید.  – حسین میرزاپور 02-12-01 در 02:22

ببخشید یعنی دستوراتی که میخوایم تو این فواصل زمانی تعیین شده اجرا بشه نباید دستور delay داشته باشه یا کلا در برنامه ای که ازین روش‌استفاده شده نبایدdelay باشه؟ چه مشکلی ایجاد میکنه؟  – راحله 02-12-01 در 06:31

بله. فرض کنید از تابع milis طوری استفاده کردید که هر ۳ ساعت یکبار یک led را با استفاده از delay به مدت ۶۰ ثانیه روشن نگه دارد. از طرف دیگر یک led دیگر هر ثانیه یکبار خاموش و روشن می‌شود. زمانی که led اول روشن می شود تا ۶۰ ثانیه که روشن می ماند led دوم در وضعیت خود متوقف خواهد ماند. و زمانبندی پروژه بهم می خورد.  – حسین میرزاپور 02-12-01 در 08:10

ببخشید آقای میرزاپور مجددا مزاحمتون میشم، هنوز متوجه نشدم چطور میشه ازین روش به جای delay استفاده کرد؟ مثلا اگر من یک ال ای دی به پایه ۳ آردینو وصل کنم و بخوام در صورت فشرده شدن کلیدی که به پایه ۴ وصل شده ۱۰ ثانیه روشن بشه بعد خاموش بشه‌چطور ازین روش به جای delay استفاده میشه؟  – راحله 02-12-06 در 05:17

ببینید با فرض اینکه یک پروسه مثل مثال اول که در کد فوق بررسی شد و قرار هست مثلا هر شش ساعت یکبار کار خاصی را انجام بدهد. اگر در ضمن آن پروسه شش ساعت یکبار بخواهید کنترل های دیگری هم انجام بدهید مانند همین مثالی که فرمودید با فشردن کلید بدون استفاده از توابع تاخیری مثل delay، یک ال ای دی به مدت ۱۰ ثانیه روشن بماند و بعد خاموش شود. خوب تابع miles رو داریم که داره کارش رو انجام میده. فرض کنید تابع miles یک ساعت دیواری هست که میکروکنترلر مرتب بهش نگاه میکنه و بعد از گذشت ۶ ساعت کاری که ازش خواستیم رو انجام میده. پس در این بین میتونیم کارهای دیگه هم ازش بخواهیم که انجام بده. مثلا با فشردن کلید مقدار miles رو میخونیم و در یک متغیر ذخیره میکنیم و پایه 3 رو هم HIGH میکنیم تا ال ای دی روشن بشه . حالا با یک شرط مثل همونی که زمان شش ساعته رو کنترل میکنه مرتب زمان فعلی رو در loop می‌خوانیم و مقدار ذخیره شده قبلی رو ازش کم میکنیم اگر این مقدار بزرگتر یا مساوی 10 ثانیه شد پایه 3 رو LOW میکنیم تا ال ای دی خاموش بشه. اینطوری میتونیم چندتا کار رو همزمان بدون استفاده از delay انجام بدیم.  – حسین میرزاپور 02-12-07 در 06:05

ممنون سعی برنامه روشن شدن ال ای دی مطالق راهنمایی شما بنویسم اگر نتونستم مزاحمتون میشم  – راحله 02-12-07 در 06:14

ببخشید این روش به حافظه فشار بیشتر نمیآره یا باعث اختلال در عملکرد میکرو و برنامه های بزرگ نمیشه؟  – راحله 02-12-07 در 06:15

خواهش میکنم. خیر اختلالی در کار میکرو و حافظه ایجاد نمیکنه. من خلاصه مطلب رو در قالب پاسخ جدید اضافه کردم تا خواندنش برای سایر دوستان راحت تر بشه  – حسین میرزاپور 02-12-08 در 08:00

افزودن دیدگاه

0

در روش فوق برای انجام چند کار به  صورت همزمان نباید از توابع تاخیری مثل delay استفاده کنیم چون تمام زمانبندی ها رو بهم میریزه. یعنی زمانی که مثلا 10 ثانیه توقف برای روشن ماندن LED با Delay ایجاد میکنیم ممکنه از زمان در حال شمارش Milies قافل بشیم و کاری که براش زمانبندی کردیم با 10ئ ثانیه تاخیر انجام بشه.

راه حل1: با فرض اینکه  قرار است برنامه شما مثلا هر شش ساعت یکبار کار خاصی را انجام بدهد. اگر در ضمن آن پروسه شش ساعت یکبار بخواهید کنترل های دیگری هم انجام بدهید مانند همین مثالی که فرمودید با فشردن کلید بدون استفاده از توابع تاخیری مثل delay، یک ال ای دی به مدت ۱۰ ثانیه روشن بماند و بعد خاموش شود. خوب تابع miles رو داریم که داره کارش رو انجام میده.

فرض کنید تابع miles یک ساعت دیواری هست که میکروکنترلر مرتب بهش نگاه میکنه و بعد از گذشت ۶ ساعت کاری که ازش خواستیم رو انجام میده. پس در این بین میتونیم کارهای دیگه هم ازش بخواهیم که سر وقتش انجام بده. یعنی نیازی نیست دوبار milies  رو برای هر کاری از اول فراخوانی کنیم. ما ساعت دیواری رو داریم کافیه برای انجام هرکاری فقط بهش نگاه کنیم، اگر زمانش فرارسیده بود اون کار رو انجام بدیم.

مثلا با فشردن کلید مقدار miles رو میخونیم و در یک متغیر ذخیره میکنیم و پایه 3 رو هم HIGH میکنیم تا ال ای دی روشن بشه . حالا با یک شرط مثل همونی که زمان شش ساعته رو کنترل میکنه مرتب زمان فعلی رو در loop می‌خوانیم و مقدار ذخیره شده قبلی رو ازش کم میکنیم اگر این مقدار بزرگتر یا مساوی 10 ثانیه شد پایه 3 رو LOW میکنیم تا ال ای دی خاموش بشه. اینطوری میتونیم چندتا کار رو همزمان بدون استفاده از delay انجام بدیم.

راه حل2: یک روش دیگه هم میتونم پیشنهاد بدم و اون استفاده از بردهای دوهسته ای مثل ESP32 و Raspberry Pi Pico هست که برای هر هسته جداگانه میتونید برنامه ریزی کنید و حتی از دستور delay  هم میتونید استفاده کنید. هر هسته جداگانه کار خودش رو انجام میده و مزاحمتی برای کار هسته دیگه نداره. ضمن اینکه این بردها دارای حافظه بیشتر و سرعت پردازش بسیار بالاتری هستند و تکنولوژی‌ اونها به روز است و جذابیت خیلی بیشتری نسبت به میکرو های 8 بیتی دارند.
پیشنهاد دیگه اینکه اگر بیش از دو  کار مجزا رو میخواهید به صورت همزمان برنامه ریزی کنید از برد Arduino Due  استفاده کنید. البته بورد های ESP32 و Raspberry Pi Pico با اینکه از آردوینو uno  پیشرفته تر و قویتر هستند از اون ارزانتر هم هستند ولی  Arduino Due گران تر است.

08 اسفند 02 در 08:18
حسین میرزاپور
111

افزودن دیدگاه


انجمن کافه‌ربات © 1400