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

آموزش راه اندازی تایمر / کانتر در برد آردوینو

سلام. آموزش استفاده از تایمر / کانتر در آردوینو (آموزش Arduino #9) را آماده کردیم.

چگونه از تایمر کانتر در آردوینو استفاده کنیم ؟

در این قسمت از آموزش های آردوینو، میخواهیم تابع Delay() استفاده نکنیم و در عوض با خود رجیستر ها کار کنیم. نکته خوب این است که میتوانیم برای این کار از نرم افزار آردوینو استفاده کنیم. ما بیت های رجیستر تایمر خود را تنظیم میکنیمو از تایمر وقفه Overflow نیز استفاده میکنیم. به این صورت که هر بار وقفه رخ داد، ال ای دی را روشن و خاموش کند. مقدار تایمر را میتوان با دکمه ها کتنرل کرد تا مدت زمان وقوع وقفه را کنترل کنیم.

اینگونه است که می توان از یک تایمر برای تولید تاخیر در برنامه آردوینو استفاده کرد. ویدیوی زیر را ببینید که با افزایش و کاهش preload با استفاده از دکمه ها، تغییر تأخیر را نشان داده ایم.

پیشنهاد میشود قبل از خواندن این آموزش ، قسمت های قبلی را بخوانید.

ابتدا مباحث تئوری را بررسی میکنیم سپس به صورت عملی با انجام یک پروژه موضوع را کاملا توضیح میدهیم.

TIMER درجاسازی شده الکترونیک چیست؟

تایمر نوعی وقفه است. مانند ساعت ساده ای است که می تواند فاصله زمانی یک رویداد را اندازه گیری کند. هر میکروکنترلر دارای یک ساعت (نوسان ساز) است که می گویند در Arduino Uno آن 16 مگاهرتز است. این مقدار مسئولیت سرعت را بر عهده دارد. یعنی هرچه فرکانس بالا تر باشد ، سرعت پردازش نیز بالا تر میرود. یک تایمر از یک شماره استفاده میکند که بسته به فرکانس ساعت ، با سرعت مشخصی شمارش میشود. در آردوینو یونو، 1/16000000 ثانیه (یا 62 نانو ثانیه) طول می کشد تا یک واحد شمارش شود.

تایمر در Arduino UNO:

در آردوینو UNO سه تایمر برای کارکردهای مختلف قرار داده شده است.

  • Timer0: این یک تایمر 8 بیتی است و در عملکرد تایمر مانند  delay() و millis() استفاده می شود.
  • Timer1: این یک تایمر 16 بیتی است و در کتابخانه سروو استفاده می شود.
  • Timer2: این یک تایمر 8 بیتی است و در تابع tone() استفاده می شود.

رجیستر های تایمر در آردوینو

برای تغییر پیکربندی تایمر، از رجیستر تایمر استفاده می شود.

1. رجیستر کنترل تایمر / کانتر (TCCRnA / B):

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

قالب فریم:
TCCR1A 7 6 5 4 3 2 1  0 
COM1A1 COM1A0 COM1B1 COM1B0 COM1C1 COM1C0 WGM11 WGM10
TCCR1B 7 6 5 4 3 2 1  0
ICNC1 ICES1 WGM13 WGM12 CS12 CS11 CS10
 پیش تقسیم کننده (Prescaler):

بیت های CS12 ، CS11 ، CS10 در TCCR1B مقدار prescaler را تعیین می کنند. از Prescaler برای تنظیم سرعت ساعت تایمر استفاده می شود. آردوینو اونو، prescalers های 1 ، 8 ، 64 ، 256 ، 1024 را دارد.

CS12 CS11 CS10 USE
0 0 0 بدون توقف
0 0 1 CLCK i/o /1 بدون از پیش تقسیم کننده
0 1 0 CLK i/o /8 با پیش تقسیم کننده
0 1 1 CLK i/o /64 با پیش تقسیم کننده
1 0 0 CLK i/o /256 با پیش تقسیم کننده
1 0 1 CLK i/o /1024 با پیش تقسیم کننده
1 1 0 منبع خارجی ساعت در پین t1 = به صورت کاهشی
1 1 1 منبع خارجی ساعت در پین t1 = به صورت افزایشی

2. رجیستر تایمر / کانتر (TCNTn)

این ثبات برای کنترل مقدار پیشخوان و تنظیم مقدار پیش لودر استفاده می شود.

فرمول برای مقدار preloader برای زمان مورد نیاز در ثانیه:

TCNTn = 65535 – (16x1010x زمان در ثانیه / ارزش پریس کالر)

برای محاسبه مقدار preloader برای timer1 برای زمان 2 Sec:

TCNT1 = 65535 – (16x1010x2 / 1024) = 34285

اگر در مورد این مطلب سوالی دارید در قسمت نظرات بپرسید

وقفه های تایمر در Arduino

ما قبلاً در مورد وقفه های آردوینو اطلاعاتی کسب کرده ایم و دیده ایم که وقایع تایمر نوعی وقفه است. وقفه های مختلف تایمر در آردوینو وجود دارد که در زیر توضیح داده شده است.

وقفه سرریز تایمر (Overflow)

هر وقت تایمر به حداکثر مقدار خود می رسد مثلاً (مثلاً (16 بیت-65535)) وقفه سرریز تایمر رخ می دهد. بنابراین، هنگامی که بیت سرریز وقفه تایمر فعال شود، یک وقفه ISR رخ میدهد که بیت TIEx موجود در TIMSKx را فعال می کند.

فرمت ISR:
ISR(TIMERx_OVF_vect)
{
}

رجیستر مقایسه خروجی (OCRnA / B):

در اینجا وقتی خروجی مقایسه مطابق باشد، وقفه رخ می دهد، سپس سرویس وقفه ISR TIMERx_COMPy_vect فراخوانی می شود و همچنین بیت پرچم OCFxy در رجیستر TIFRx تنظیم می شود. این ISR با تنظیم بیت فعال در OCIExy موجود در رجیستر TIMSKx فعال می شود.

ضبط ورودی تایمر:

سپس وقتی وقفه ورودی تایمر رخ داد، سرویس وقفه ISR TIMERx_CAPT_vect فراخوانی می شود و همچنین بیت فلگ ICFx در TIFRx (رجیستر پرچم تایمر وقفه) تنظیم می شود. این ISR با تنظیم بیت فعال در ICIEx موجود در رجیستر TIMSKx فعال می شود.

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

پروژه استفاده از تایمر کانتر در آردوینو

در اینجا یک پروژه آردوینو را راه اندازی میکنیم که با فشردن دکمه ها، تاخیر مورد نیاز برای روشن و خاموش شدن ال ای دی تنظیم میشود.

توضیحات مدار پروژه تایمر کانتر آردوینو

در تصویر زیر میتوانید شماتیک مدار پروژه را ببینید.

مدار پروژه Timer Counter آردوینو

اتصالات مدار بین Arduino UNO و نمایشگر LCD 16×2:

ال سی دی  کاراکتری 16×2 آردوینو Uno
VSS GND
VDD +5V
V0 پتانسیومتر برای تعیین کنتراست
RS 8
RW GND
E 9
D4 10
D5 11
D6 12
D7 13
A +5V
K GND

دو دکمه با مقاومت 10 کیلو اهم به پین های آردوینو 2 و 4 وصل شده اند و یک ال ای دی از طریق یک مقاومت 2.2 کیلو اهم به پین ​​7 آردوینو وصل می شود.

قطعات مورد نیاز

  1. آردوینو UNO
  2. دکمه – دو عدد
  3. LED (هر رنگ)
  4. مقاومت کیلو اهم – دو عدد
  5. مقاومت 2.2 کیلو اهم
  6. ال سی دی کاراکتری 16×2
قطعات مورد نیاز را از فروشگاه قطعات آیرنکس تهیه کنید.

پس از اتصال قطعات، مدار شما مانند تصویر زیر میشود :

چگونه از تایمر کانتر در Arduino استفاده کنیم ؟

کد پروژه تایمر کانتر در آردوینو

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

دوستان فهمیدن کد کاملا نیازمند خواندن این آموزش میباشد تا به طور کامل با فرمول های تایمر کانتر آشنا شوید : آموزش جامع تایمر / کانتر در میکروکنترلر های AVR 

از آنجا که LCD برای نمایش مقدار پیش تقسیم کننده از ال سی دی کاراکتری 16*2 استفاده می شود، بنابراین از کتابخانه LiquidCrystal.h استفاده می کنیم.

#include<LiquidCrystal.h>          

پین آند LED که به پین 7 آردوینو وصل شده است به عنوان ledPin تعریف می شود.

 #define ledPin 7

سپس پین های ارتباط با ال سی دی تعریف میشود.

  LiquidCrystal lcd(8,9,10,11,12,13);

سپس مقدار پیش تقسیم کننده 3035 را به مدت 4 ثانیه تنظیم کنید.

 float value = 3035;   

در مرحله بعدی (void setup) ، ابتدا LCD را در حالت 16×2 تنظیم کرده و برای چند ثانیه پیام خوش آمدید نمایش میدهیم.

  lcd.begin(16,2);
  lcd.setCursor(0,0);
  lcd.print("ARDUINO TIMERS");
  delay(2000);
  lcd.clear();

سپس پین LED را به عنوان پین OUTPUT و دکمه های فشار را به عنوان پین ورودی تنظیم میکنیم.

  pinMode(ledPin, OUTPUT);
  pinMode(2,INPUT);
  pinMode(4,INPUT);

سپس تمامی وقفه ها را غیرفعال میکنیم.

  noInterrupts();       

سپس Timer1 آغاز می شود.

TCCR1A = 0;
TCCR1B = 0;

مقدار تایمر preloader تنظیم شده است (در ابتدا با مقدار 3035).

  TCNT1 = value;  

سپس مقدار پیش تقسیم شده 1024 در رجیستر TCCR1B تنظیم می شود.

 TCCR1B |= (1 << CS10)|(1 << CS12);   

وقفه سرریز تایمر در رجیستر تایمر وقفه Mask فعال شده است تا از ISR استفاده شود.

TIMSK1 |= (1 << TOIE1);      

در آخر همه وقفه ها فعال هستند.

 interrupts();            

اکنون ISR را برای تایمر وقفه سر ریز که مسئولیت روشن و خاموش کردن LED با استفاده از digitalWrite را بر عهده دارد، بنویسید. هر زمان که وقفه سرریز تایمر رخ دهد حالت تغییر می کند.

ISR(TIMER1_OVF_vect)                   
{
  TCNT1 = value;                               
  digitalWrite(ledPin, digitalRead(ledPin) ^ 1); 
}

در void loop () مقدار پیش تقسیم کننده با استفاده از ورودی ها (دکمه) افزایش یافته یا کاهش می یابد و همچنین مقدار آن در ال سی دی کاراکتری 16×2 نشان داده می شود.

  if(digitalRead(2) == HIGH)
  {
    value = value+10;             //افزایش preload 
  }
  if(digitalRead(4)== HIGH)
  {
    value = value-10;            //کاهش preload 
  }
  lcd.setCursor(0,0);
  lcd.print(value);
}

کد کامل پروژه:

موارد موجود در فایل : سورس کامل

4.9 (16 نفر)

برای دریافت مطالب جدید کانال تلگرام یا پیج اینستاگرام ما را دنبال کنید.

محمد رحیمی

محمد رحیمی هستم. سعی میکنم در آیرنکس مطالب مفید قرار بدهم. سوالات مربوط به این مطلب را در قسمت نظرات همین مطلب اعلام کنید. سعی میکنم در اسرع وقت به نظرات شما پاسخ بدهم.

24 نظر

  1. سلام من میخوام از خروجی های ocr1a , ocr1b در تایمر 1 استفاده کنم که روی پین های 9 و 10 آردینوی اونو دو تا موج مربع با فرکانس 100 هرتز و دیوتی سایکل های مختلف که توی برنامه تعریف کنم داشته باشم برای کنترل دو تا موتور دی سی تو کدویژن راخت میتونم انجام بدم ولی تو آردینو نتونستم کمک میهوام ممنون میشم اگه کمکم کنید

    1. سلام عزیز، مسئله اصلی رجیستر ها هست مقدار دهی بیت ها در کدویژن و آردوینو تفاوتی نداره
      برای یادگیری برنامه نویسی آردوینو میتونید دوره آموزش آردوینو رو مشاهده کنید

    2. سلام
      با سپاس از استاد رحیمی عزیز بخاطر مطالب آموزشی مفیدی که در سایت قرار میدهند،
      دوست عزیز محیط کدنویسی آردوینو برای راحتی کار برنامه نویسان ابداع شده است و نیازی نیست که شما با ثبات ها و رجیستر های تایمر ها درگیر شوید. و با استفاده از کتابخانه هایی که برای این منظور طراحی شده اند، براحتی میتوانید این کار را انجام دهید.
      در آردوینو اونو شما می توانید از کتابخانه TimerOne استفاده کنید و براحتی کد خود را ایجاد کنید.
      در این کتابخانه با استفاده از دستور Timer1.initialize(1E6 / frequency); میتوانید فرکانس pwm خروجی را روی 1 هرتز الی 1 مگاهرتز تنظیم کنید. مقدار frequency میتواند بین 1 تا 1000000 باشد. و با استفاده از دستور Timer1.pwm(pwmPin, dutyCycle); میتوانید دیوتی سایکل (dutyCycle) مورد نظر خود را بین 0 الی 1023 تنظیم کنید که 1023 معادل 100% است و pwmPin هم میتواند پین 9 یا 10 باشد.
      در طی اجرای برنامه می توانید با استفاده از دستور Timer1.setPeriod(1E6 / frequency); فرکانس کاری را تغییر دهید و همچنین با استفاده از دستور Timer1.setPwmDuty(pwmPin, dutyCycle); دیوتی سایکل را نیز تغییر دهید. منظور از 1E6هم همان یک میلیون است. و آردوینو آن را می شناسد.
      شاد و پیروز باشید.

    3. #include /* کتابخانه تایمر 1 */

      const int pwmPin1 = 9; /* پین خروجی شکل موج */
      const int pwmPin2 = 10; /* پین خروجی شکل موج */
      unsigned long frequency = 100; /* فرکانس بر حسب هرتز از 10 هرتز تا یک مگاهرتز میتواند باشد */
      unsigned int dutyCycle1 = 512;
      unsigned int dutyCycle2 = 128;

      void setup(void)
      {
      pinMode(pwmPin1, OUTPUT);
      pinMode(pwmPin2, OUTPUT);
      Timer1.initialize(1E6 / frequency); /* تنظیم فرکانس تایمر 1 */
      Timer1.pwm(pwmPin1, dutyCycle1); /* تولید شکل موج با دیوتی سایکل مورد نظر */
      Timer1.pwm(pwmPin2, dutyCycle2); /* تولید شکل موج با دیوتی سایکل مورد نظر */
      }

      void loop(void)
      {
      }

  2. سلام
    چرا مقدار این دو تا رجیستر صفر شده ؟
    TCCR1A = 0;
    TCCR1B = 0;

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

  3. ببخشید من پروژه رو اوکی کردم مرسی از کمکتون
    فقط اسم اهنگو میتونید بگید؟

  4. سلام و وقت بخیر
    من می خوام زمان کلید زنی من ذخیره بشه تا ازش استفاده کنم..
    بعنوان مثال اگر کلید ۴ ثانیه قطع بود ذخیره بشه.. از چه روشی باید استفاده کنم ؟
    ممنون میشم راهنماییم کنید

  5. سلام چرا دیمرم هنگ میکنه؟ برنامه ولتاژ و جریان متناوب امدازه میگیره

    1. سلام جناب، پروژه دیمر میخواهید راه اندازی کنید یا ولتاژ و جریان متر؟

  6. سلام میخواهم یه تایمر داشته باشم با دو خروجی مجزا وهر تایمر قابل برنامه گرفتن دو زمان برای روشن و خاموش شدن در 24 ساعت وهمچنین
    برای هفته قابل برنامه ریزس باشد میتوانم از اردینو اونو و ساعت ds3231 استفاده کنم؟ با سپاس از شما

    1. سلام جناب، بله میتونید استفاده کنید.

  7. سلام من یه برنامه نوشتم تایمر یک ساعت و دو ساعت و سه ساعت ولی برای هر تایم یه کلید گذاشتم درستم عمل میکنه میخواستم راهنمایی کنید جه جور به جای سه تا کلید یک کلید بذارم.با شکر.

    1. سلام جناب. یک متغیر عددی تعریف کنید. این شرط رو بذارید که هر وقت کلید فشرده شد، متغیر +1 بشه و بعد شرط های مختلف تعیین کنید برای اعداد مختلفی که در متغیر بوجود میاد.

  8. سلام برای برنامه نویسی میکرو کنترلر با چه برنامه ای بریم بهتره؟

    1. سلام. خیلی سوال کلی ای هست. بستگی به سطح پروژتون داره. اگر پروژه ساده ای دارید بسکام، آردوینو و کدویژن خوب هستند. و در صورتی که میخواهید از صفر آموزش ببینید پیشنهاد میکنم با آردوینو شروع کنید تا در حالت کلی آشنایی پیدا کنید و بعدش به سراغ اتمل استودیو برید.

  9. سلام میخوام کلید کولر تایمر دار بسازم میشه کمکم کنید.با تشکر.

    1. سلام. میخواهید تعیین کنید تو چه ساعت هایی در روز کولر روشن باشه؟

    2. سلام نه.میخوام مثلا وقای روشنه بهش یک ساعت یا دوساعت تایم بدم تا خاموش بشه.

    3. کار ساده ای هست پروژه خاصی برای این کار نداریم اما مطالب قسمت آموزش های آردوینو رو از اول بخونید خیلی راحت در همون جلسات ابتدایی میتونید این کار رو انجام بدید.

  10. سلام.من میخام هر 24 ساعت یکبار در زمان خاصی اردوینو کاری رو انجام بده.میشه از delay استفاده کنم؟

    1. اینطوری ممکنه نتیجه دقیقی نگیرید. از ماژول DS3231 استفاده کنید تا زمانتون دقیق باشه و با قطع و وصل برق از دست نره. آموزش های زیر به شما کمک میکنند :
      چگونه با آردوینو یک پروژه یادآور بسازیم ؟
      پروژه ساعت زنگ دار با نور قابل تنظیم توسط بلوتوث گوشی اندروید در آردوینو (آلارم+RGB)

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

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *