آردوینو آموزش آردوینو پروژه های آردوینو

برنامه نویسی چند نخی یا Multi threading آردوینو DUE

آموزش پردازش موازی در آردوینو DUE
نوشته شده توسط علیرضا قربانی

برنامه نویسی چند نخی یا Multi threading  آردوینو DUE

مبحث thread   یک مبحث مهم در برنامه نویسی می‌باشد. بدون استفاده از Thread  معمولا برنامه‌ها عمل‌کرد بالایی را  پیدا نمی‌کنند.هنگامی که درون یک برنامه دو یا چند بخش نیاز به پردازش همزمان داشته باشند  می‌توانیم روی هر قسمت  Thread  جدا گانه اجرا  کنیم.چند نخی یا Multi Thrending  در واقع می‌تواند چند وظیفگی یا تقسیم پردازش یا برنامه به بخش‌های مجزا را منجر شود.با این سبک برنامه‌نویسی می‌توانیم چند پردازش را به صورت همزمان اجرا کنیم. مثلا می‌توانیم به صورت همزمان مقدار چند سنسور را خوانده و در همان حال چند بازوی رباتیک را کنترل نمود. آردوینو DUE نیز از  میان سایر آردوینو‌ها از برنامه نویسی چندنخی پشتیبانی می‌کند و با آن می‌توان برنامه‌هایی با چند پردازش همزمان اجرا نمود. در ادامه آموزش با مرجع تخصصی آردوینو ، دیجی اسپارک همراه باشید.

(توجه داشته باشید که این آموزش صرفا مخصوص آردوینو DUE می‌باشد)

کتابخانه‌ای به نام Scheduler  مختص آردوینو DUE وجود دارد که به وسیله آن می‌توانید چند تابع را به صورت همزمان در برنامه اجرا کنید. به عبارت دیگر برنامه شما می‌تواند دارای چند loop باشد که همگی بدون ایجاد وقفه در دیگری در حال پردازش می‌باشند. در واقع توسط این کتابخانه CPU  به چند بخش تقسیم می‌شود و هر بخش وظیفه اجرای یک loop را بر عهده می‌گیرد.

در ابتدای شروع کار با ین کتابخانه  باید  طبق دستور زیر کتابخانه Scheduler را به برنامه فرخوانی کنیم.

#include <Scheduler.h>

در مرحله‌ی بعدی می‌بایست برای هر قسمتی که می‌خواهیم عملیات چند نخی یا همان Thread را برا روی آن اجرا کنیم یک تابع بنویسیم.برای مثال در قطعه کد زیر ما ۳ عدد loop می‌خواهیم در برنامه ایجاد کنیم و عملیات Thread را بر روی آن‌ها اجرا کنیم به این معنی که این سه عدد loop به طور همزمان برنامه‌های داخلشان بدون تداخل با یکدیگر اجرا شوند.

#include <Scheduler.h>

void setup()
{

}

// حلقه ی اول
void loop()
{

}

// حلقه ی دوم
void loop2()
{

}

// حلقه ی سوم
void loop3()
{

}

سپس نوبت به استفاده از تابع زیر می‌رسد:

Scheduler.startLoop(loop name)

توسط این تابع درون setup برنامه ، loop‌های نوشته شده را به برنامه معرفی می‌کنیم. توجه داشته باشید که loop  شماره ۱ به طور پیش‌فرض معرفی می‌شود و loop های بعد از شماره ۱ را باید معرفی نمود .پس کد‌های ذکر شده در بالا را به صورت زیر توسعه می‌دهیم:

 

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

 

دسترسی کامل به آموزش برای اعضای دیجی اسپارک امکان پذیر است. بخش اصلی آموزش شامل سورس کدهای توسعه داده شده توسط مهندس‌های دیجی اسپارک است. به همین دلیل این آموزش خاص و یکتاست. برای استفاده از آن بایستی عضویت تهیه کنید. تبادل نظر با کاربران و پرسش سوال رایگان است و میتوانید از بخش نظرات همین آموزش اقدام کنید.

 

 

در مرحله بعدی باید در آخرین loop موجود در تابع  yield را صدا بزنیم تا cpu در بین loop ها عملیات سوئیچ را انجام دهد. در صورتی که تابع yield فراخوانی نشود ، برنامه قفل می‌کند و دیگر هیچ عملیاتی را انجام نمیدهد .پس مطابق کدهای فوق باید در پایان  loop3  تابع yield را فراخواند همانند کد زیر:

// حلقه ی سوم
void loop3()
{
yield();
}

 


 

چکیده: با استفاده از چندنخی در آردوینو DUE می‌توان پردازش‌های سنگین را دسته بندی کرد بدون اینکه در حین انجام یک پردازش سنگین قسمت‌های دیگر برنامه موقف شود. برای مثال طبق آموزش داده شد شما میتوانید حتی در loop شماره ۳ از با استفاده از delay یک ناخیر به میزان ۲۰ ثانیه ایجاد کنید بدون اینکه در loop شماره۱ و ۲  اینن تاخیر تاثیری ایجاد کند و loop شماره ۱ و ۲ به صورت طبیعی به کار خود ادامه می‌دهد.

 

پروژه برنامه نویسی چند نخی آردوینو

در این پروژه یک سه عدد LED را به پین‌های شماره ۸ ، ۹ و ۱۳ متصل می‌کنیم.سپس در loop شماره ۱ ، LED متصل به پین شماره۸ را با تاخیر ۱ ثانیه به صورت چشمک زن در می‌آوریم و همچنین در loop شماره ۲ ، LED متصل به پین شماره ۹ را با تاخیر ۱۰۰ میلی‌ثانیه به صورت چشمک زن در می‌آوریم و همچنین در loop شماره ۳ ، به وسیله ارتباطط سریال و دریافت دو کاراکتر ۰ و ۱ ، LED متصل به پین شماره ۳ را خاموش روشن می‌کنیم.در صورتی که کد‌های زیر را بر روی آردوینو DUE آپلود کنید مشاهده خواهید کرد که delay های موجود در loop ها بر روی هم تاثیری نمی‌گزارند و هر loop به صورت مستقل پردازش می‌شود.

// Include Scheduler since we want to manage multiple tasks.
#include <Scheduler.h>

int led1 = 8;
int led2 = 9;
int led3 = 13;

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

  // Setup the 3 pins as OUTPUT
  pinMode (led1, OUTPUT);
  pinMode (led2, OUTPUT);
  pinMode (led3, OUTPUT);

  // اضافه کردن loop2 , loop3 به منظور ایجاد برنامه نویسی چند نخی
  // loop شماره ی ۱ به صورت پیش فرض به برنامه معرفی می شود
  Scheduler.startLoop (loop2);
  Scheduler.startLoop (loop3);
  }

// Task no.1: blink LED with 1 second delay.
void loop ()
  {
  digitalWrite (led1, HIGH);
  delay (1000);
  digitalWrite (led1, LOW);
  delay (1000);
  }

// Task no.2: blink LED with 0.1 second delay.
void loop2 ()
  {
  digitalWrite (led2, HIGH);
  delay (100);
  digitalWrite (led2, LOW);
  delay (100);
  }

// Task no.3: accept commands from Serial port
// '۰' turns off LED
// '۱' turns on LED
void loop3 ()
  {
  if ( Serial.available () ) {
    char c = Serial.read ();
    if ( c == '0' ) {
      digitalWrite (led3, LOW);
      Serial.println ("Led turned off!");
      }
    if ( c == '1' ) {
      digitalWrite (led3, HIGH);
      Serial.println ("Led turned on!");
      }
    }
  delay (10000);
  // IMPORTANT:
  // We must call 'yield' at a regular basis to pass
  // control to other tasks.
  yield ();
  }

درباره نویسنده

علیرضا قربانی

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

تبادل نظر و رفع عیب با ثبت دیدگاه

۵۹ دیدگاه

  • سلام جناب مهندس خسته نباشید
    با سایر آردوینو ها هم میتونیم از این تکنیک استفاده کنیم مثلا آردوینو Uno
    پیش نهادی هم داشتم : لطفآ آموزش هایی به این سبک قرار بدین .به نظر من آموزش هایی به این سبک خیلی مفیدن .مثل آموزش دیبانس کلید که من همیشه با کلید مشکل داشتم ولی وقتی اون مطلب شما رو خوندم تونستم مشلم را رفع کنم

    بازم ممنون
    پیروز باشیید

  • بسیار ممنون از لطفت…. خسته نباشید ……
    واقعا این سبک مطلب نوشتن که سریع میره سر اصل مطلب خیلی کمک می کنه خیلی زیاد، چرا که وسط یک پروژه آدم دیگه وقت نداره بره هزارتا آسمون ریسمون نوشته شده تو مطالب مرجع را بخونه ….

    • مثل سایت d**313 اقای دمپرچیلو که حال ادم بد میشه حین خوندن مطالبش . داستان نویس کودک باید میشد نه نویسنده سایت علمی

      • با سلام
        ضمن تشکر از ارایه نظر شما، لطفا اگر انتقادی به سایت‌های دیگر دارید، جوری اعلام کنید که باعث تغییرات مثبت در آن‌ها شود.

  • سلام
    من با آپلود کردن کد روی آردوینو due مشکل دارم اگه میشه آموزش کاملشو روی سایت بزارین.
    ممنون

      • سلام مهندس من به کمک شما خیلی نیاز دارم من یک اردینو due گرفتم ولی به یک مشکلی برخورد همه جارو هم گشتم نتونستم پیدا کنم من می خواستم اگه لطف کنین کمک کنید من می خواسم ماژول وای فای esp8266 به اردینو وصل کنم تو برنامه نویسی که میکنم تو اردینو ینو و غیره کار میکنه ولی وقتی می خوام به این ارینو اپلودش کنم ارور میده مشکل از بردم نیست چون برنامه های دیگه رو تست کردم متاسفانه تو نرم افزار ارور میده برنامه های ساده رو ساپورت میکنه میشه اپلودش کرد ولی این ببرنامه که نوشتم فقط تو این برد ارور میده از هر دو پورتشم تست کردم حافظه اشم پاک کردم ولی باز نشده از کتابخانه های some serial و softwareserial استفاده کردم از ارینو uno هم نمی تونم استفاده کنم چون خطاش زیاده دستوراتی که میگیره اردینو چون باید همزمان عمل کنه خطای سخت افزار بالا میره

  • سلام خسته نباشید
    برد اردوینو uno این قابلیت را ندارد؟
    پروژه من اندازه گیری همزمان رطوبت و دما به صورت غیر تماسی است که دو سنسور جداگانه است
    و بردی که تهیه کردم uno هست

    • نخیر متاسفانه تنها بردی که این قابلیت را دارا میباشد Arduino DUE هست. البته شما میتوانید در آردوینو Uno , دستور داده گیری از سنسور ها را پشت سریکدیگر بگذارید و با تقریب خیلی خوبی از اینکه داده ها در زمان بسیار نزدیکی به یکدیگر خوانده می‌شود خیالتان را راحت کنید. فرکانسی که آردوینو Uno دستور ها را میخواند از محدوده مگاهرتز میباشد . ( ۱۲ مگاهرتز )

  • با سلام و عرض ادب
    در هر یک از این لوپ ها که به طور همزمان انجام میشه ، اگر تابعی فراخوانی بشه بازهم عمل چندنخی انجام میشه ؟
    و اگر یه تابع مشترک در دو لوپ فراخوانی شود چه اتفاقی می افتد ؟
    با تشکر از سایت عالی و مطالب مفیدتون

    • درود بر شما
      ضمن تشکر از توجه شما، در مورد سوال اول، بله عمل مربوطه انجام میشود.
      در مورد سوال دوم، هر دو لوپ اجرا میشود.

    • با سلام
      ضمن تشکر از توجه شما، از آنجایی که برد ESP دارای تراشه تک هسته‌ای است. چنین قابلیتی را نخواهد داشت. اگر از دوستان دیگر، روشی برای این موضوع میدانند، خواهش می‌کنم که تجربه‌شان را بیان کنند.

  • سلام با عرض خسته نباشید و تشکر از راهنمایی جنابعالی
    دوست عزیز در بردهای دیگر آردوینو مانند mega2560 چگونه باید برنامه موازی را نوشت.

    • با سلام
      ضمن تشکر از توجه شما، از آنجایی که برنامه نویسی چند نخی نیازبه پردازش سنگین‌تری نسبت به برنامه معمولی دارد. با برد آردوینو Mega2560 از آنجایى که از تراشه AVR بهره میبرند، امکان برنامه نویسى چند خطى را ندارد. درضمن پردازش موازى با برنامه نویسى چندخطى تفاوت دارد.

  • سلام خسته نباشید
    من میخواستم که از برد آردوینو به عنوان فلایت کنترل در کوادکوپترم استفاده کنم. سوالی که دارم اینه که برنامه هایی که براش نوشتم جدا هستن. یعنی برنامه مربوط به رادیو کنترل و برنامه مربوط به فلایت کنترل رو باید در یک آردوینو بریزم تا اینکه بتونم کواد رو کنترلش کنم. سوالم اینه که چطور میتونم چنین کاری رو انجام بدم؟ راهش فقط همینه؟
    یه سوال دیگه اینکه من وقتی برنامه ای رو روی آردوینو میریزم و بعدش بدون ریستارت کردنش یه برنامه دیگه رو روش میریزم، آیا اون برنامه اولی خود به خود پاک میشه؟ کلا به مشکل خوردم. از طرفی هم توی نت دیدم که با فقط یدونه آردوینو UNO کواد ساختن و به خوبی هم پرواز میکنه.
    ممنون میشه منو در این مورد راهنمایی کنید.

    • با سلام
      ضمن تشکر از توجه شما، در مورد سوال اول، این کار قابل انجام است و برای ترکیب کدها باید دانش برنامه نویسی خود را بالا ببرید.
      مورد دوم: بله برنامه ی اول به کلی پاک می‌شود.

  • سلام مهندس. یه سوال خارج این موضوع داشتم پروژه های آردوینو uno روی آردوینو due اجرا میشه ؟ یا به عبارتی تمام کارهایی که uno میتونه انجام بده due هم میتونه انجام بده؟

    • باسلام
      ضمن تشکر از توجه شما، پاسخ به این سوال همیشه قطعی نیست، برای انتقال کدها از UNO به برد Arduino DUE پارامترهایی از جمله کتابخانه به کار رفته در کدها و شیوه کدنویسی در این موضوع تاثیر گذار است. این موارد را با بررسی آموزش‌های داخل دیجی اسپارک می‌توانید دریابید.

  • با سلام
    ممنون از سایت مفیدتان.
    ببخشید کدی که در این صفحه گذاشته اید اجرا نمی شود و ERROR می دهد.
    در برنامه من دستور STARTLOOP بی رنگ می شود در حالی در کد شما رنگی است.
    لطفا راهنمایی کنید.

  • با عرض سلام و خسته نباشید لطفا آردینو هایی که از مولتی ترد استفاده میکنند رو در یک پستی معرفی کنید

    و اینکه لطفا نحوه نوشتن ترد روی میکرو های avr رو هم در صورت توان توضیح دهید

    • سلام
      تعدا حلقه ها بستگی به توان پردازش دارد.
      همچنین از دیگر کاربرانی که در این زمینه اطلاعات دارند، تقاضا دارم در بحث شرکت کنند.

  • با سلام و عرض ادب و تشکر از مطلب جالبتون
    در برد های ARM ی که بر پایه ی کامپایلر آردوینو قابل بوت شدن هستند مثل STM32F103C8T6 که مانند due دارای پردازنده آرم ۳۲ بیتی کورتکس m3 است آیا از کتابخانه مذکور برای چند نخی می توان کمک گرفت؟

    • با سلام
      خیر، البته برای مشخص شدن این موضوع می‌بایست فایل و سورس اصلی کتابخانه را بررسی بفرمایید. برای استفاده در بردهای دیگر معمولا به کتابخانه همان برد نیاز است. از دیگر کاربران که در این خصوص تجربه دارند، تقاضا دارم تا در این بحث شرکت کنند.

  • سلام.
    سوالی که پیش میاد اینه که:
    ۱٫تا چند thread میشه روی برد تعریف کرد؟همین سه تا یا بیشترهم امکان پذیر هست؟
    ۲٫میکروی Arduino Due در حالت پیش فرض موقع خرید روی ۸۴MHz تنظیم شده یا کمتر هست و باید تنظیمش کرد؟

    • با سلام
      بله تعداد مورد نظر بسته به نوع پروژه شما مشخص می‌گردد.
      طبق اطلاعات گفته شده در دیتاشیت فرکانس آن در ۸۴ مگاهرتز تعریف شده است.

  • سلام،ممنون از مطالب بسیار خوبتون،من یک اردیونو due دارم،تو پروژه ای که دارم استفاده می کنم در عملکرد چند نخی در قسمتی از برنامه مجبور هستم دو پارامتر مثلاً aوb را در دو حلقه مجزا حساب کنم(مثلا a در حلقه ی یک و bدر حلقه ی دوم) و هم زمان این دو پارامتر را در حلقه سوم با هم مقایسه بکنم(در هر لحظه مقدار a و b در حال تغییر است،میخواهم در هر لحظه که این دو تغییر میکنن تو همان لحظه در حلقه ی سوم این مقایسه انجام شود) آیا میتونم این کارو در برنامه نویسی چند نخی انجام بدم در صورت مقدور بودن ممنون میشم راهنمایی کنید،و سوال دیگه،اگر امکانش هست درباره ی yeild بیشتر توضیح بدید.ممنون

  • سلام،ممنون از مطالب بسیار خوبتون،من یک اردیونو due دارم،تو پروژه ای که دارم استفاده می کنم در عملکرد چند نخی در قسمتی از برنامه مجبور هستم دو پارامتر مثلاً aوb را در دو حلقه مجزا حساب کنم(مثلا a در حلقه ی یک و bدر حلقه ی دوم) و هم زمان این دو پارامتر را در حلقه سوم با هم مقایسه بکنم(در هر لحظه مقدار a و b در حال تغییر است،میخواهم در هر لحظه که این دو تغییر میکنن تو همان لحظه در حلقه ی سوم این مقایسه انجام شود) آیا میتونم این کارو در برنامه نویسی چند نخی انجام بدم در صورت مقدور بودن ممنون میشم راهنمایی کنید،و سوال دیگه،اگر امکانش هست درباره ی yeild بیشتر توضیح بدید.ممنون

  • سلام خسته نباشید
    میخواستم یه سوال درباره اتصال I2C با برد اردوینو DUE بپرسم
    من هنگامی که یه سنسور که ارتباط I2C داره رو به برد متصل میکنم وداده ها رو برای یکبار میخونه و مرتبا داده ای رو که بار اول خونده نشون میده یا در موارد دیگه حداکثر داده که میتونه خونده بشه رو میخونه و همونو نشون میده و دیگه تغییر نمیکنه .
    جالب اینجاس همین سنسور با همین کد در اردوینوUNO کاملا سالمه و کار میکنه
    اگر بتونید راهنمایی بفرمایید بینهایت ممنون میشم

  • سلام جناب مهندس
    یه مشکل با کتابخانه برخوردم .وبعد چند ساعت تلاس نتونستم مشکل رو برطرف کنم
    برنامه آردونیو به این قرار است

    #include
    int pb = 2; // push button
    int led1 = 3; // LED 1 ( void loop )
    int led2 = 4; // LED 2 ( void loop 2 )
    int mo = 5 ; // motor ( void loop 3 )

    void setup ()
    {

    // Setup the 3 pins as OUTPUT and 1 pin as input
    pinMode (led1, OUTPUT);
    pinMode (led2, OUTPUT);
    pinMode (mo, OUTPUT);
    pinMode (pb, INPUT_PULLUP);

    scheduler.startLoop(loop2);
    scheduler.startLoop(loop3);
    }

    // Task no.1: blink LED with 0.75 second delay.
    void loop ()
    {
    digitalWrite (led1, HIGH);
    delay (750);
    digitalWrite (led1, LOW);
    delay (750);
    }

    // Task no.2: blink LED with 0.15 second delay.
    void loop2 ()
    {
    digitalWrite (led2, HIGH);
    delay (150);
    digitalWrite (led2, LOW);
    delay (150);
    }

    // working or not workin motor by pushing button
    void loop3 ()
    {
    int m = digitalRead(2); // push button
    if (m == HIGH) // when push button be pushed, the motor stop working
    {
    digitalWrite(5, LOW);
    }
    else //when push button be released, motor working
    {
    digitalWrite(5, HIGH);
    }

    yield ();
    }
    البته اینجا راست چین اومده ولی اگه تو notepad کپی کنید درست نمایش میدهمشکل اینجاست که در هر حالتی که امتحان کردم از قسمت
    scheduler.startLoop(loop2) ; and scheduler.startLoop(loop3); a
    ایراد میگیره
    حرف a در بالا فقط به جهت درست نمایش دادن متن انگیسی گذاشتم و شما نادیده بگیرید

  • سلام آموزش خیلی عالی و کاربردی بود برنامه نویسی چند نخی از برد های اردوینو فقط مختص به آردوینو DUE میشه یا با برد های دیگه اردوینو که میکروکنترلر آرم دارند مثل مگا و STM32 هم میشه؟
    اگه میشه، نوشتنشون هم مثل همین آموزش هست یا نه؟

    و سوال بعدیم اینکه برای پردازش تصویر که قیمت مناسبی هم داشته باشن (زیر ۱ میلیون) کدوم برد آردوینو بهترین گزینه هست؟
    و یا برای اینکه یه پردازش تقریبا خوبی داشته باشم باید از رزبری پای یا بردهای openMV یا از esp32cam استفاده کنم؟

  • سلام بر دوستان
    توی سوالات خوندم چندنفر پرسیده بودن که چند حلقه میتوان استفاده کرد
    در اصل از n حلقه میتوان استفاده کرد یعنی بی نهایت
    همچنین مقدار رم استفاده شده امکان پردازش فوق سنگین نمیده یعنی نمیشه گفت از ۵۰ تا حلقه سنگین استفاده میشه کرد
    ۵۰ تا حلقه سبک یا ۱۰ تا حلقه متوسط یا ۵ تا حلقه سنگین

  • با سلام …من سه حلقه برا کنترل همزمان سه استپ موتور طبق دستوران بالا ایجاد کردم ولی کدها بصورت ترتیبی اجرا میشه نه موازی!!!!آردوینوی مورد استفتدم dueمیباشد

  • سلام وقتتون بخیر .
    من یه پروژه دارم که باید تقریبا ۱۲ ماژول رو با ارتباط (۱۲c=8)و(SPI=4) رو کنترل کنم و نشون رو به یک نمایشگر وصل کنم برای یه همچین پروژه ای بهتره که از اردینو Due استفاده کنم یه رزبری پای ؟ درضمن اینکه این پروژه از فضای کمی برخوردار است

    • با سلام
      این سوال اساسا درست نیست. بستگی به اینکه شما به چه زبان برنامه نویسی تسلط دارید بایستی یکی از این دو برد را انتخاب کنید. برد آردوینو هم توانایی اجرای درخواست شما را دارد ولی بایستی مهارت کافی در c++ و مدیریت حافظه داشته باشید.

  • سلام رزبری پای یه همچین قابلیتی رو داره ؟ اگه داره میشه آموزشش رو بزارید