همانطور که در مقاله قبلی دیدیم تنظیمات عملکرد زمان سنجی/شمارش می توانست بر اساس تنظیمات رجیسترهای مرتبط با میکروکنترلر اختصاصی ماژول آردوینو انجام پذیرد. روش دیگر برای کنترل ماژول های تایمر استفاده از کتابخانه های تایمر می باشد. یکی از این کتابخانه ها، کتابخانه Arduino-timer است. در اینجا به این موضوع خواهیم پرداخت، و در مورد نحوه نصب و استفاده از کتابخانه arduino-timer بحث خواهیم کرد. استفاده از آن می تواند بسیار ساده تر از آنچه قبلاً در آموزش وقفه های تایمر آردوینو انجام دادیم باشد.

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

کتابخانه تایمر آردوینو

کتابخانه Arduino-Timer کاربران را قادر می‌سازد تا رویدادها (وظایف) مبتنی بر تایمر را بدون نیاز به برنامه‌نویسی در سطح رجیستر برای ماژول‌های تایمر پیکربندی کنند. از توابع داخلی ()millis و micros مبتنی بر تایمر استفاده می‌کند.

1- استفاده از کتابخانه Arduino-Timer

برای استفاده از کتابخانه Arduino-Timer، باید فایل هدر آن را اضافه کنید و یک شی از کلاس Timer ایجاد کنید.

کتابخانه را به این شکل قرار دهید.

#include <arduino-timer.h>

یک نمونه تایمر پیش‌فرض با تنظیمات پیش‌فرض ایجاد کنید.

;()auto MyTimer = timer_create_default

قادرید پیکربندی‌هایی را که مطلوب شماست برای نمونه تایمر مانند شکل زیر مشخص کنید.

Timer<10> MyTimer; // 10 concurrent tasks, using millis as resolution

Timer<10, micros> MyTimer; // 10 concurrent tasks, using micros as resolution

Timer<10, micros, int> MyTimer; // 10 concurrent tasks, using mi

همانطور که مشاهده می کنید 3 قالب مختلف برای ایجاد یک نمونه Timer وجود دارد. این به شما امکان می‌دهد حداکثر تعداد کارهایی را که باید با نمونه تایمر، وضوح تناوب کار (بر حسب میلی‌ثانیه یا میکرو ثانیه)، و نوع داده‌های آرگومان برای توابع کنترل‌کننده وظیفه (در صورت نیاز) استفاده کنید، مشخص کنید.

 توابع اصلی کتابخانه Arduino-Timer

تابع اصلی در کتابخانه Arduino-Timer عبارت است از .tick() و شما باید آن را در ()loop فراخوانی کنید در حالی که میکروکنترلر IDLE است تا تعداد تیک ها را پیش برده و وظایف را در زمانی که زمان تناوب آنها فرا می رسد ارسال کنید.


}()void loop

  ;() MyTimer.tick

{

نکته: اگر میکروکنترلر مشغول انتظار است یا کار دیگری را انجام می دهد که خیلی طول می کشد، بنابراین تابع ()tick را به طور مکرر فراخوانی نمی کند، لذا خطر از دست دادن ضرب الاجل وظایف دوره ای اختصاص داده شده به نمونه تایمر را دارید.

 ایجاد عملکرد مدیریت وظیفه در Arduino-Timer

برای ایجاد یک تابع مدیریت وظیفه، از الگوی تعریف تابع زیر استفاده کنید.

bool Task_Handler(void *argument /* optional argument given to in/at/every */)

}

   // Handle The Task

   // ...

   return true; // true: repeat the action, false: to stop the task

{

تابع Task handler می‌تواند یک آرگومان اختیاری بگیرد در حالی که آن را به شی تایمر با استفاده از هر یک از توابع

()at.  

()every.

()in.

که در ادامه به آن خواهیم پرداخت اختصاص خواهد داد. شما فقط می توانید آن را در صورت عدم نیاز حذف کنید و عملکرد Task handler خود را به این صورت اعلام کنید.

bool Task1_Handler(void *)

}

  // Handle The Task

  // ...

  return true; // repeat? true

{

اختصاص وظایف در کتابخانه Arduino-Timer

پس از ایجاد نمونه ای از کلاس تایمر، می توانید وظایف (توابع) را که می خواهید به طور دوره ای اجرا کنید به آن اختصاص دهید. و این می تواند به 3 روش مختلف بسته به هدف شما انجام شود.

فرض کنید می خواهید تابع ()Task1_Handler را به نمونه تایمر (MyTimer) وصل کنید، می توانید از هر یک از سه روش زیر استفاده کنید.

()every.


MyTimer.every(interval, Task1_Handler); // Calls Task1_Handler every   (interval) units of time.

()at.


MyTimer.at(time, Task1_Handler); // Calls Task1_Handler at a specific   (time).

()in.


MyTimer.in(delay, Task1_Handler); // Calls Task1_Handler i

 لغو وظایف در کتابخانه Arduino-Timer

برای لغو یک وظیفه، هنگام اختصاص دادن آن به نمونه تایمر، حتماً یک مدیر  برای آن کار دریافت کنید. در اینجا مثالی از نحوه انجام آن آورده شده است.

;uto Task1Handle = MyTimer.every(interval, Task1_Handler)

;MyTimer.cancel(Task1Handle)

برای لغو همه کارهای در حال اجرا، از تابع زیر استفاده کنید.

;()MyTimer.cancel

نصب کتابخانه آردوینو تایمر

می توانید کتابخانه Arduino-Timer را به صورت دستی از GitHub دانلود و نصب کنید، یا آن را در خود Arduino IDE نصب کنید. برای اینکار manage libraries را از بالای صفحه IDE آردوینو باز کنید. یعنی Tools > Manage Libraries. عبارت arduino-timer را جستجو کنید. سپس بر روی Install کلیک کنید و اجازه دهید تا نصب تمام شود.

اکنون، می‌توانید به راحتی از کتابخانه Arduino-Timer استفاده کنید و مثال های داخل کتابخانه را بررسی کنید تا به شما در شروع کار کمک کند.

اکنون به سراغ نمونه‌های کد عملی می‌رویم تا این کتابخانه Arduino-Timer را برای ایجاد رویدادهای دوره‌ای در هر دو زمان (ms و μs) آزمایش کنیم.

مثال کتابخانه Arduino-Timer (تولید میلی ثانیه)

در این پروژه نمونه، کتابخانه Arduino-Timer را آزمایش خواهیم کرد. ما دو کار با دوره های 80 میلی ثانیه و 35 میلی ثانیه ایجاد خواهیم کرد. که هر کدام یک پین خروجی LED را تغییر می دهند. و ما زمان بندی خروجی را با استفاده از اسیلوسکوپ اندازه گیری می کنیم تا مطمئن شویم که کتابخانه تایمر همانطور که انتظار می رود کار می کند.

کد نمونه کتابخانه آردوینو تایمر

در اینجا لیست کد کامل این مثال آردوینو تایمر (ms Tasks) آمده است.

include <arduino-timer.h>#

define LED1_PIN 13

define LED2_PIN 8

;Timer<2, millis> MyTimer

bool Task1_Handler(void *)

}

  digitalWrite(LED1_PIN, !digitalRead(LED1_PIN)); // Toggle LED1

  return true; // repeat? true

{

bool Task2_Handler(void *)

}

  digitalWrite(LED2_PIN, !digitalRead(LED2_PIN)); // Toggle LED2

  return true; // repeat? true

{

}()void setup

 ; pinMode(LED1_PIN, OUTPUT)

; pinMode(LED2_PIN, OUTPUT)

 ; MyTimer.every(80, Task1_Handler)

 ; MyTimer.every(35, Task2_Handler)

{

}()void loop

  MyTimer.tick(); // tick the timer

{

توضیح کد:

ابتدا باید کتابخانه را وارد کنیم و یک شی تایمر ایجاد کنیم.

#include <arduino-timer.h>

Timer<2, millis> MyTimer;

توابع ()Task1_Handler() , Task2_Handler

این تابع کنترل کننده Task1 است که می خواهیم به صورت دوره ای هر 80 میلی ثانیه اجرا شود. که در آن پین خروجی LED1 را تغییر می دهیم.

bool Task1_Handler(void *)

}

  digitalWrite(LED1_PIN, !digitalRead(LED1_PIN)); // Toggle LED1

  return true; // repeat? true

{

این تابع کنترل کننده Task2 است که مایلیم به صورت دوره ای هر 35 میلی ثانیه اجرا شود. که در آن پین LED2 خروجی را تغییر می دهیم.

bool Task2_Handler(void *)

}

  digitalWrite(LED2_PIN, !digitalRead(LED2_PIN)); // Toggle LED2

  return true; // repeat? true

{

()setup

در تابع ()setup حالت پین‌های LED را روی خروجی تنظیم می‌کنیم و توابع Task1_Handler و Task2_Handler را به نمونه تایمری که ایجاد کرده‌ایم وصل می‌کنیم و تنظیم می‌کنیم که به ترتیب در هر بازه زمانی (80 و 35 میلی‌ثانیه) فراخوانی شوند.

}()void setup

  ;pinMode(LED1_PIN, OUTPUT)

  ;pinMode(LED2_PIN, OUTPUT) 

  ;MyTimer.every(80, Task1_Handler)

  ;MyTimer.every(35, Task2_Handler)

{

()loop

در تابع ()loop باید تابع ()tick. را که تابع اصلی کتابخانه Arduino-Timer است به طور مداوم فراخوانی کنیم.

}()void loop

  MyTimer.tick(); // tick the timer

{

شبیه سازی پروتئوس

در اینجا نتیجه شبیه سازی این پروژه در شبیه ساز Proteus (ISIS) است. شبیه‌سازی TinkerCAD برای این مثال، رفتار قابل اعتمادی را ایجاد نمی‌کند، شاید به دلیل عدم دقت در مدل میکروکنترلر در محیط شبیه‌سازی باشد. شبیه‌سازی پروتئوس بسیار دقیق‌تر است و دقیقاً مانند برد آردوینو UNO واقعی عمل می‌کند.

علاوه بر این، ما مجموعه ای بهتر و قدرتمندتر از ابزارهای اندازه گیری مجازی (اسیلوسکوپ، ژنراتور تابع، مولتی متر، ترمینال سریال مجازی و غیره) داریم.


این لینک را بررسی کنید تا به شما در شروع شبیه سازی پروژه های آردوینو در محیط شبیه سازی پروتئوس کمک کند.

نتایج تست عملی

در اینجا نتیجه اجرای این پروژه نمونه بر روی برد Arduino UNO و گرفتن سیگنال خروجی در (اسیلوسکوپ ذخیره سازی دیجیتال) را بطور واقعی مشاهده می کنید.

این یک رویداد نوسان پین کامل 80 میلی‌ثانیه و یک رویداد نوسان پین 35 میلی‌ثانیه دیگر را نشان می‌دهد، دقیقاً همانطور که انتظار داشتیم و در شبیه‌سازی دیده‌ایم.

مثال کتابخانه تایمر آردوینو (تولیدμs)

در این پروژه مثال، وضوح میکروثانیه کتابخانه Arduino-Timer را آزمایش خواهیم کرد. ما یک کار دوره ای ایجاد می کنیم که هر 100 میکرو ثانیه اجرا می شود، که در آن یک پین LED خروجی را تغییر می دهیم. سپس، زمان‌بندی شکل موج حاصل را اندازه‌گیری می‌کنیم تا مطمئن شویم کتابخانه تایمر مطابق انتظار کار می‌کند.

کد نمونه کتابخانه تایمر آردوینو

در اینجا کد کاملی برای این مثال آردوینو تایمر (μs تولید) آمده است.

include <arduino-timer.h>#

define LED1_PIN 13

;Timer<1, micros> MyTimer

bool Task1_Handler(void *)

}

  digitalWrite(LED1_PIN, !digitalRead(LED1_PIN)); // Toggle LED

  return true; // repeat? true

{

}()void setup

  ;pinMode(LED1_PIN, OUTPUT)

  // Call The Task1_Handler Function Every 100μs

 ; MyTimer.every(100, Task1_Handler)

{

}()void loop

  MyTimer.tick(); // tick the timer

{

شبیه سازی با پروتئوس:

اندازه گیری واقعی:


2- استفاده از کتابخانه TimerOne.h

کتابخانه TimerOne آردوینو به کاربران امکان می دهد تایمر 16 بیتی را برای تولید و مدیریت وقفه های دوره ای پیکربندی و استفاده کنند و همچنین سیگنال های PWM را با فرکانس و سیکل وظیفه قابل کنترل تولید کنند.

استفاده از کتابخانه آردوینو TimerOne

برای استفاده از کتابخانه آردوینو TimerOne، باید فایل هدر آن را به این صورت در کد خود قرار دهید.

include <TimerOne.h>#

می توانید از API های ارائه شده برای پیکربندی ماژول تایمر، وصل کردن یک کنترل کننده وقفه به آن و غیره استفاده کنید. در ادامه به بررسی توابع زمان‌بندی و عملکردهای کنترل PWM در کتابخانه TimerOne می‌پردازیم.

 توابع زمان سنجی آردوینو TimerOne 

Timer1.initialize(period)

برای استفاده از روش های دیگر باید ابتدا این متد را فراخوانی کنید. شما می توانید به صورت اختیاری دوره تایمر را در اینجا (در میکروثانیه) مشخص کنید، به طور پیش فرض روی 1 ثانیه تنظیم شده است. توجه داشته باشید که این امر باعث اختلال در analogWrite() برای پین های دیجیتال 9 و 10 در Arduino UNO می شود.

در اینجا یک مثال از نحوه مقداردهی اولیه Timer1 برای داشتن یک دوره 10 میلی ثانیه است.

Timer1.initialize(10000); // Fire An Interrupt Every 10ms

Timer1.setPeriod(period)

دوره را بر حسب میکروثانیه تنظیم می کند. حداقل دوره یا بالاترین فرکانسی که این کتابخانه پشتیبانی می کند 1 میکروثانیه یا 1 مگاهرتز است. حداکثر دوره 8388480 میکروثانیه یا حدود 8.3 ثانیه است. توجه داشته باشید که تنظیم دوره، وقفه الصاقی و فرکانس و چرخه وظیفه هر دو خروجی pwm را به طور همزمان تغییر می دهد.

در اینجا مثالی از نحوه تنظیم دوره Timer1 به مدت 1ms آورده شده است.

Timer1.setPeriod(1000)

Timer1.attachInterrupt(function, period)

یک تابع را در بازه زمانی مشخص شده در میکروثانیه فراخوانی می کند. توجه داشته باشید که اگر زمانی که آن را فراخوانی می‌کنید، مقداری را در میکروثانیه به عنوان آخرین پارامتر وارد کنید، می‌توانید به صورت اختیاری دوره تناوب را با این تابع تنظیم کنید.

در اینجا مثالی از نحوه الصاق وقفه به رویداد دوره‌ای Timer1 آورده شده است تا عملکرد کنترل‌کننده Timer1_ISR را با تناوب ثابت 1 میلی‌ثانیه اجرا کند.

Timer1.attachInterrupt(Timer1_ISR, 1000)

()Timer1.detachInterrupt

وقفه الصاقی را غیرفعال می کند.

()Timer1.detachInterrupt

توابع تولید PWM مربوط به کتابخانه TimerOne

Timer1.pwm(pin, duty, period)

یک شکل موج PWM روی پین مشخص شده ایجاد می کند. پین های خروجی برای Timer1 پایه های PORTB 1 و 2 هستند، بنابراین شما باید بین این دو یکی را انتخاب کنید، انتخاب هر پایه دیگری نادیده گرفته می شود. در Arduino UNO، اینها پین‌های دیجیتال 9 و 10 هستند. در آردوینو مگا، پین‌های خروجی برای Timer3 پورتE هستند و مطابق با 2،3 و 5 در ماژول مگا هستند.

سیکل کار به عنوان یک مقدار 10 بیتی مشخص شده است، بنابراین هر چیزی بین 0 تا 1023 است. توجه داشته باشید که اگر هنگام فراخوانی آن، مقداری را در میکروثانیه به عنوان آخرین پارامتر وارد کنید، می توانید به صورت اختیاری دوره را با این تابع تنظیم کنید.

توجه

خروجی های  PWM مرتبط با کتابخانه TimerOne فقط برای پین های 9 و 10 آردوینو در دسترس هستند. اینها پین‌های خروجی سخت‌افزاری (OC1A و OC1B) برای خروجی‌های تطبیق مقایسه Timer1 هستند.

سیکل وظیفه (Duty Cycle) تنها 10 بیت است با وجود این واقعیت که ماژول Timer1 یک تایمر 16 بیتی است و می تواند سیگنال PWM با وضوح 16 بیت تولید کند اما با بالا رفتن فرکانس PWM وضوح کاهش می یابد. 

در اینجا مثالی از نحوه پیکربندی یک کانال خروجی PWM در پین 9 برای تولید سیگنال PWM چرخه کاری 50 درصد در فرکانس 1 کیلوهرتز آورده شده است.

Timer1.pwm(9, 512, 1000)

Timer1.setPwmDuty(pin, duty)

این تایع یک راه میانبر سریع برای تنظیم سیکل وظیفه pwm برای یک پین معین اگر قبلاً آن را با فراخوانی تابع Timer1.pwm()  پیش تر تنظیم کرده باشید هست. با این کار از سربار (فعال کردن مد pwm برای پین، تنظیم رجیستر جهت داده، بررسی تنظیمات دوره اختیاری و غیره) که هنگام فراخوانی تابع Timer1.pwm() اجباری هستند، جلوگیری می کند.

در اینجا مثالی برای نحوه استفاده از آن برای تغییر مقدار چرخه وظیفه به 10% در خروجی pin9 آورده شده است.

Timer1.setPwmDuty(9, 102)

Timer1.disablePwm(pin)

PWM را برای پین مشخص شده خاموش می کند تا بتوانید از آن پین برای کار دیگری استفاده کنید. در اینجا نحوه استفاده از آن برای غیرفعال کردن خروجی PWM در پین 9 آورده شده است.

Timer1.disablePwm(9)

سایر توابع مفید کتابخانه TimerOne

اینها برخی از توابع مفید دیگر در کتابخانه TimerOne هستند که ممکن است گاهی اوقات در پروژه های مختلف از آنها استفاده کنید.

void stop();  // Pause Timer1 By Disabling The Clock

void start(); // Resume Timer1 Clock

void restart(); // Clear The Timer Ticks

unsigned long read(); // Reads the time since last rollover 

نصب کتابخانه آردوینو TimerOne

شما می توانید کتابخانه Arduino TimerOne را به صورت دستی از GitHub دانلود و نصب کنید، یا ، آن را در خود Arduino IDE نصب کنید. به مسیر Tools > Manage Libraries رفته و عبارت TimerOne.h را جستجو کنید. سپس روی گزینه Instal کلیک کنید.

اکنون می‌توانید به راحتی از کتابخانه TimerOne استفاده کنید و مثال های داخلی کتابخانه را بررسی کنید تا به شما در شروع کار کمک کند.

اکنون به سراغ مثالهای عملی می‌رویم تا این کتابخانه Arduino TimerOne را برای ایجاد وقفه‌های تایمر دوره‌ای آزمایش کنیم.

در این پروژه نمونه، کتابخانه TimerOne را آزمایش خواهیم کرد. ما یک رویداد وقفه تایمر دوره‌ای 10 میلی‌ثانیه ایجاد می‌کنیم که در آن یک پین LED خروجی را تغییر می‌دهیم. و ما زمان بندی خروجی را با استفاده از اسیلوسکوپ اندازه گیری می کنیم تا مطمئن شویم که کتابخانه تایمر همانطور که انتظار می رود کار می کند.

include <TimerOne.h># 

void Timer1_ISR(void)

}

  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));

{

void setup(void)

}

  pinMode(LED_BUILTIN, OUTPUT)

  Timer1.initialize(10000); // Fire An Interrupt Every 10ms


{  Timer1.attachInterrupt(Timer1_ISR)

}void loop(void)

{

زیرروال اینتراپت یا همان تابع کنترل کننده وقفه تایمر برای وقفه های دوره ای 10 میلی ثانیه ای در نظر گرفته شده است. که در آن در هر 10 میلی ثانیه یکبار، پین LED خروجی را تغییر وضعیت می دهیم. (یعنی اگر خاموش است آن را روشن و اگر روشن است آن را خاموش می کنیم)

شبیه سازی با پروتئوس:


تست آزمایشگاهی:

مثالTimerOne 20kHz PWM

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

ما هر دو کانال PWM TimerOne (pin9 و pin10) را به طور همزمان کنترل خواهیم کرد. هر خروجی PWM دارای فرکانس 20 کیلوهرتز است و چرخه کاری از 0٪ تا 100٪ (محو شدن) و از 100٪ به 0٪ (محو شدن) خواهد رفت. چرخه وظیفه خروجی PWM در هر کانال مکمل دیگری خواهد بود (اثر معکوس).

include <TimerOne.h>#

void setup(void)

}

  ;pinMode(9, OUTPUT)

;  pinMode(10, OUTPUT)

  ;Timer1.initialize(50)

  ;Timer1.pwm(9, 0)

  ;Timer1.pwm(10, 1023)

{

void loop(void)

}

  for (int i = 0; i < 1023; i++)

  }

   ; Timer1.setPwmDuty(9, i)

    ;Timer1.setPwmDuty(10, (1023 - i))

    ;delay(1)

 {

  for (int i = 1023; i > 0; i--)

  }

   ; Timer1.setPwmDuty(9, i)

   ; Timer1.setPwmDuty(10, (1023 - i))

    ;delay(1)

 {

{