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

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

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

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

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

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

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

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 آردوینو

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

مدار پروژه 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 ( آموزش AVR #8)

از آنجا که 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);
}

کد کامل :

#include<LiquidCrystal.h>  
#define ledPin 7
LiquidCrystal lcd(8,9,10,11,12,13);
float value = 3035;         
void setup()
{
  lcd.begin(16,2);
  lcd.setCursor(0,0);
  lcd.print("ARDUINO TIMERS");
  delay(2000);
  lcd.clear(); 
  pinMode(ledPin, OUTPUT);
  pinMode(2,INPUT);
  pinMode(4,INPUT); 
  noInterrupts();   
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = value;       
  TCCR1B |= (1 << CS10)|(1 << CS12);
  TIMSK1 |= (1 << TOIE1);         
  interrupts();                
}
ISR(TIMER1_OVF_vect)           
{
  TCNT1 = value;                          
  digitalWrite(ledPin, digitalRead(ledPin) ^ 1);  
}
void loop()
{
  if(digitalRead(2) == HIGH)
  {
    value = value+10;      
  }
  if(digitalRead(4)== HIGH)
  {
    value = value-10;    
  }
  lcd.setCursor(0,0);
  lcd.print(value);
}

فیلم عملکرد پروژه

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

قسمت بعد : بزودی …

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

محمد رحیمی

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

12 نظر

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

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

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

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

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

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

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

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

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

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

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

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

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