ساخت ساعت دیجیتال یکی از رایجترین پروژه هایی است ، که هر شخص بعد از آشنایی با میکروکنترلر ها و برنامه نویسی انجام می دهد . با جستجو در موتورهای جستجوگر پروژه های متعددی برای ساخت ساعت دیجیتال بر روی lcd کاراکتری ، ساعت دیجیتال بر روی سون سگمنت و ساعت دیجیتال بر روی تابلو روان یافت می شود . در سایت میکرونیک ما انواع پروژه های مختلف ساخت ساعت دیجیتال را قرار خواهیم داد . اما در این مقاله به ساخت ساعت دیجیتال بر روی seven segment خواهیم پرداخت .
موضوعاتی که در این مقاله به آنها پرداخته خواهد شد :
آموزش ساخت ساعت دیجیتال با rtc داخلی avr
ابتدا ما یک پروژه رایگان ساخت ساعت دیجیتال بر روی سون سگمنت را با استفاده از الگوریتمی بسیار ساده و قابل فهم شروع خواهیم کرد و در انتها چندین پروژه کامل و تجاری را با استفاده از انواع ماژول های rtc بسیار دقیق قرار خواهیم داد .
در این پروژه ما قصد داریم به تشریح برنامه نوشته شده به صورت خط به خط و به زبانی ساده بپردازیم و شما پس از مطالعه آن به طور کامل با نحوه کارکرد ساعت دیجیتال آشنا می شوید و خود می توانید به راحتی یک ساعت دیجیتال را بسازید .
در این پروژه قصد داریم توسط (RTC(Real Time Clock میکروکنترلر avr با کامپایلر codevision یک ساعت دیجیتال بسازیم و آن را روی سون سگمنت به روش مولتی پلکس به نمایش در آوریم . در اکثر میکروکنترلرهای avr ، تایمر دو می تواند به عنوان rtc عمل کند که در اینصورت کلاک مورد نیاز آن به صورت آسنکرون از طریق یک کریستال ساعت خارجی با فرکانس ۳۲٫۷۶۸KHZ تامین می گردد .
روش مولتی پلکس برای نمایش ساعت دیجیتال روی سون سگمنت
برای نمایش اعداد در روش معمولی ما باید برای هر سون سگمنت یک پورت یا یک آی سی لچ به کار ببریم . اما در روش مولتی پلکس نیاز ما به سخت افزار به شدت کاهش می یابد . در روش نمایش به صورت مولتی پلکس تمامی سون سگمنت ها به صورت موازی به یکدیگر اتصال داده شده و یک دیتاباس را تشکیل می دهند . بنابراین تنها یک پورت از میکروکنترلر ما اشغال می شود .
حال نکته اینجاست که اگر عددی را بر روی باس ارسال کنیم این عدد بر روی تمامی سون سگمنت ها قرار می گیرد و تمامی سون سگمنت ها این عدد را نشان خواهند داد . برای حل این مشکل ما باید از پایه مشترک (پایه تغذیه) هر سون سگمنت به عنوان پایه های کنترلی استفاده کنیم و هر زمان که ما فرمان دادیم سون سگمنت روشن شده و عدد مورد نظر را نشان دهد . به این صورت که پس از ارسال هر عدد بر روی باس ، ما تنها فرمان روشن شدن یک سون سگمنت را می دهیم آن هم در مکانی که می خواهیم عددمان نمایش داده شود.
با این روش مشکل روشن شدن همه سون سگمنت ها حل می شود اما هنوز کار تمام نشده زیرا در هر لحظه ما فقط یک عدد را می توانیم نشان دهیم در صورتی که ما می خواهیم چندین عدد را به صورت پیوسته به نمایش در آوریم . برای رفع این مشکل ، ما می توانیم از خطای دید انسان استفاده کنیم ، می دانید که هر تصویر برای مدت زمان کوتاهی در ذهن انسان باقی می ماند بنابراین اگر ما اعداد را با سرعتی کمتر از ماندن تصویر در ذهن انسان بر روی سون سگمنت اسکن کنیم اعداد را به صورت پیوسته و بدون پرش خواهیم دید.
تایمر دو در میکروکنترلر avr
به طور کلی عملکرد تایمر دو مشابه عملکرد تایمر صفر در میکروکنترلر avr می باشد ؛ با این تفاوت که نمی توان به عنوان کانتر از آن استفاده نمود ؛ اما می توان با اتصال یک کریستال خارجی ۳۲٫۷۶۸KHZ به پایه های ,TOCS1 TOCS2 از آن در وضعیت آسنکرون جهت rtc استفاده نمود . تایمر دو خود دارای یک prescaler مجزا از بقیه تایمرها می باشد ؛ که با تقسیم فرکانس ایجاد شده توسط کریستال ۳۲٫۷۶۸KHZ بر ۱۲۸ می توان به زمان سرریز یک ثانیه که مناسب برای عملکرد ساعت است دست پیدا کرد .
پیکربندی تایمر دو توسط Codewizard
بزرگترین مزیت کامپایلر codevision نسبت به بقیه کامپایلرهایی که برنامه نویسی در محیط آنها به زبان c می باشد وجود codewizard یا جادوگر می باشد . زیرا شما بدون نیاز به دانش زیاد از رجیسترهای میکرومنترلر avr می توانید تمامی بخش های سخت افزاری میکروکنترلر avr را به راحتی پیکربندی کنید . که در اینجا ما نیز می خواهیم تایمر دو را در مد آسنکرون توسط Codewizard پیکربندی کنیم .
ابتدا وارد محیط جادوگر شده سپس وارد زبانه Timer2 شوید و clock source را از system clock به TOSC1 pin تغییر دهید که در اینصورت کلاک تایمر دو جدا از کلاک سیستم و به صورت آسنکرون از روی پایه های TOSC1 , TOSC2 تامین می گردد .
حال باید مقدار clock value را روی PCK2/128 قرار دهیم .که در صورت استفاده از کریستال ۳۲٫۷۶۸ کیلو هرتز روی پایه های TOSC1,TOSC2 می توان به سرریز یک ثانیه دست پیدا کرد و تایمر دو را به rtc یا ساعت زمان واقعی تبدیل کرد و با انتخاب تیک overflow interrupt می توان وقفه تایمر دو را فعال کرد که پس از سر ریز یک ثانیه وقفه اتفاق می افتد .
شرح سخت افزار :
در این مدار atmega8 هسته اصلی می باشد و وظیفه تمامی محاسبات را بر عهده دارد . ۷۴HC245 آی سی بافر است و نقش ایزوله کردن و تقویت جریان را دارد ، البته خروجیهای AVR توانایی روشن کردن LED را به صورت مستقیم دارند اما در صورت استفاده از سون سگمنت در ابعاد بزرگتر باید از بافر استفاده شود . مقاومتهای ۲۲۰ اهم برای محافظت از سون سگمنتها در برابر اضافه جریان قرار داده شده است . کریستال ۳۲٫۷۶۸ khz کلاک تایمر دو را بصورت آسنکرون برای رسیدن به سرریز یک ثانیه تامین می کند و کلاک اصلی برنامه توسط نوسانساز RC داخلی که روی ۸Mhz قرار داده شده تامین می گردد.
برای نمایش اعداد از یک سون سگمنت شش تایی از نوع کاتد مشترک استفاده شده است . همچنین برای کاهش سخت افزار می توان از قسمت نمایش ثانیه صرف نظر کرده و از یک سون سگمنت چهارتایی استفاده نمود .
برای نمایش ساعت نیاز است که اعداد به کد معادل برای سون سگمنت تبدیل شوند به این منظور آی سی های دیکودر BCD TO 7S با نام های ۷۴۴۸ برای سون سگمنت های کاتد مشترک و ۷۴۴۷ برای سون سگمنت های آند مشترک بکار برده می شود ، برای کاهش سخت افزار به صورت نرم افزاری کدهای معادل برای سون سگمنت را تبدیل کرده ایم و دیگر نیازی به استفاده از آی سی های دیکودر نمی باشد . برای تنظیم کردن مقادیر ساعت از سه سوئیچ استفاده شده است .
شرح نرم افزار :
به طور کلی برنامه از چهار قسمت اصلی تشکیل شده :
تابع main که پیکره اصلی برنامه است .
زیربرنامه وقفه تایمر دو که هر ثانیه یک بار اتفاق می افتد .
تابع set_time که وظیفه کلید خوانی و تنظیم مقادیر ثانیه ، دقیقه و ساعت را بر عهده دارد .
تابع display که وظیفه نمایش و اسکن اعداد را بر عهده دارد .
#include <mega8.h> #include <delay.h> #define comm_port PORTC #define data_port PORTD void set_time(void); void display(void); flash char cathode_seg[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //-------------------------۰----۱----۲----۳----۴----۵----۶----۷----۸----۹--- signed char second=0,minute=0,hour=0; unsigned char key,dot, pointer; unsigned char dot_set_min,dot_set_hour,dot_set_sec; void main(void) { PORTB=0x00; DDRB=0x00; PORTC=0x00; DDRC=0xFF; PORTD=0x00; DDRD=0xFF; ASSR=0x08; TCCR2=0x05; TCNT2=0x00; OCR2=0x00; TIMSK=0x40; #asm("sei") while (1) { set_time(); display(); } } //************************************************************************* interrupt [TIM2_OVF] void timer2_ovf_isr(void) { if (dot==0) { pointer = ~pointer & 0b10000000; second++; if (second > 59) { second=0; minute++; if (minute>59) { minute=0; hour++; if(hour>23) { hour=0; } } } }; } //*************************************************************************** void set_time(void) { key=PINB & 0b00000111; switch (key) { /////press set button case 0b00000001: dot++; switch (dot) { case 1 : dot_set_sec=0b10000000; dot_set_min=0b00000000; dot_set_hour=0b00000000; pointer=0; break; case 2: dot_set_sec=0b00000000; dot_set_min=0b10000000; dot_set_hour=0b00000000; pointer=0; break; case 3: dot_set_sec=0b00000000; dot_set_min=0b00000000; dot_set_hour=0b10000000; pointer=0; break; default: if (dot >= 4) { dot=0; dot_set_sec=0b00000000; dot_set_min=0b00000000; dot_set_hour=0b00000000; } }; break; /////press up button case 0b00000010: switch (dot) { case 1 : second++; if (second>59) second=0; break; case 2 : minute++; if (minute>59) minute=0; break; case 3: hour++; if (hour>23) hour=0; break; }; break; ////press DOWN button case 0b00000100: switch (dot) { case 1 : second--; if (second<0) second=59; break; case 2 : minute--; if (minute<0) minute=59; break; case 3: hour--; if (hour<0) hour=23; break; }; break; }; } //******************************************************************** void display(void) { unsigned char i; for(i=0;i<100;i++){ data_port=cathode_seg[hour / 10] | dot_set_hour ;comm_port=0b11111110;delay_us(250);comm_port=0xff; data_port=cathode_seg[hour % 10] | dot_set_hour| pointer;comm_port=0b11111101;delay_us(250);comm_port=0xff; data_port=cathode_seg[minute / 10] | dot_set_min ;comm_port=0b11111011;delay_us(250);comm_port=0xff; data_port=cathode_seg[minute % 10] | dot_set_min | pointer;comm_port=0b11110111;delay_us(250);comm_port=0xff; data_port=cathode_seg[second / 10] | dot_set_sec ;comm_port=0b11101111;delay_us(250);comm_port=0xff; data_port=cathode_seg[second % 10] | dot_set_sec ;comm_port=0b11011111;delay_us(250);comm_port=0xff; }; }
زیر برنامه تابع set_time
در این قسمت زیر برنامه تابع set_time قرار دارد که عمل کلیدخوانی در آن صورت می پذیرد و شامل سه بخش اصلی می شود :
۱٫ فشرده شدن کلید set که با هر بار فشرده شدن هر کدام از قسمتهای ثانیه ، دقیقه یا ساعت را قابل تنظیم می کند .
۲٫فشرده شدن کلید up در صورتی عمل می کند که قبل از آن توسط کلید set یکی از قسمتهای ثانیه ، دقیقه یا ساعت را انتخاب کرده باشیم و با هر بار فشرده شدن یک واحد به مقادیر ثانیه ، دقیقه یا ساعت می افزاید .
۳٫ فشرده شدن کلید down در صورتی عمل می کند که قبل از آن توسط کلید set یکی از قسمتهای ثانیه ، دقیقه یا ساعت را انتخاب کرده باشیم و با هر بار فشرده شدن یک واحد از مقادیر ثانیه ، دقیقه یا ساعت می کاهد .
زیر برنامه تابع display
در این قسمت ، زیر برنامه تابع display قرار دارد که وظیفه آن نمایش اعداد ثانیه ، دقیقه و ساعت بر روی سون سگمنت است . در آن سعی شده تمامی دستورات مربوط به نمایش هر عدد در یک خط نوشته شود تا به خوانایی و سادگی برنامه بیافزاید .
در اینجا برای نمایش هر یک از اعداد ثانیه ، دقیقه و ساعت نیاز است که قسمتهای یکان و دهگان هر عدد بصورت مجزا از یکدیگر تفکیک شوند که جهت این امر از الگوریتمی بسیار ساده استفاده شده به عنوان مثال اگر مقدار ساعت برابر با عدد۲۳ باشد برای جدا کردن رقم دهگان آن کافی است تا عدد ۲۳ را توسط عملگر / بر عدد ۱۰ تقسیم کنیم ۲۳ /۱۰=۲٫۳ و چون متغییر hour از نوع flout تعریف نشده فقط مقدار صحیح آن که عدد ۲ باشد برگردانده می شود .
برای جدا کردن رقم یکان کافی است تا عدد ۲۳ را توسط عملگر % بر عدد ۱۰ تقسیم کنیم ۲۳%۱۰=۲٫۳ که در اینصورت فقط مقدار باقیمانده تقسیم که عدد ۳ است برگردانده می شود و اعداد حاصل از تقسیم به عنوان عدد آرایه cathode_seg به کاربرده می شوند به این دستور data_port=cathode_seg [hour/10] دقت کنید . با توجه به مثال فوق خواهیم داشت data_port=cathode_seg [2] و این دستور دومین عدد از آرایه cathode_seg را که کد عدد دو (۰X5B) برای سون سگمنت است به data_port ارسال می کند .
در ادامه برای نمایش عدد ۲ بر روی سون سگمنت باید توسط دستور comm_port=0b11111110 سون سگمنت متناظر با رقم دهگان ساعت روشن شود و توسط دستور delay_ms(4) برای مدت چهار میلی ثانیه عدد ۲ روی سون سگمنت نمایش داده می شود . در نهایت توسط دستور comm_port=0xff سون سگمنت خاموش شده و آماده نمایش عدد بعد می شود .
اگر ما توسط دستور comm_port=0xff سون سگمنت را خاموش نکنیم و عدد بعد را ارسال کنیم چون هنوز comm_port ما برای نمایش عدد قبلی روشن است برای لحظات کوتاهی عدد جدید را نشان خواهد داد و در عمل باعث می شود یک سایه از عدد قبل را بر روی سون سگمنتها داشته باشیم ؛ که این امر هنگام شبیه سازی در نرم افزار پروتئوس مشهود نمی باشد.
حلقه for در زیر برنامه display روی نمایش اعداد بی تاثیر است و برای ایجاد یک تاخیر در عمل کلید خوانی بکار برده شده اگر این تاخیر ایجاد نشود چون زیر برنامه های set_time و display به صورت مداوم و با سرعت بالایی در حال اجرا هستند وقتی ما کلیدی را بفشاریم تا زمانی که کلید را رها کنیم چندین بار زیر برنامه set_time اجرا می شود و کنترل دقیقی روی تنظیم مقادیر ساعت را نخواهیم داشت به همین منظور می توان با مقدار دهی متغییر i در حلقه for میزان تاخیر در کلید خوانی را تغییر داد .
فیلم زیر نحوه عملکرد برنامه بالا می باشد . در این پروژه ساعت دیجیتال بر روی سون سگمنت به روش مولتی پلکسر عمل رفرش سون سگمنتها را انجام می دهد .
ساعت دیجیتال با ماژول سون سگمنت tm1637 توسط کدویژن – آردوینو – stm32
در پروژه قبل برای نمایش و اسکن ساعت دیجیتال بر روی سون سگمنت از روش مالتی پلکسر استفاده کردیم ، در این روش بخشی از توان پردازشی میکروکنترولر صرف رفرش سون سگمنتها می شد ، که این کار در بدنه اصلی برنامه و تابع main می تواند برنامه نویس را با محدودیت هایی روبرو کند ، یکی از روشهای مناسب برای کاستن محدودیت های برنامه ، قرار دادن برنامه رفرش سون سگمنتها در وقفه یکی از تایمرهای میکروکنترلر می باشد .
روش دیگر درایو و رفرش سون سگمنتها استفاده از آی سی هایی مثل tm1637 برای راه اندازی مستقل سون سگمنتها می باشد . ماژول tm1637 به همراه 4 عدد سون سگمنت ، با قیمتی ارزان ، می تواند وظیفه راه اندازی و رفرش سون سگمنتها را کامل بر عهده بگیرد و میکروکنترلر تنها با یک دستور می تواند مقادیر ساعت را بر روی سون سگمنتها نمایش دهد .
ساعتی که با rtc داخلی میکروکنترلر در ابتدای همین مقاله ساختیم ، به دلایلی که اشاره شد ممکن است دقیق نباشد و ساعت بعد از سپری شدن مدت زمانی عقب بماند . به همین دلیل برای اینکه پروژه ساعت دیجیتال دقیق و تجاری بسازیم از ماژول های ساعت مانند ds1307 , ds3231 استفاده می کنیم .
ماژول های ساعت ds1307 , ds3231 هر دو توسط یک شرکت ساخته شده اند ، ماژول ds3231 جدیدتر است و به دلیل داشتن جبرانساز داخلی فرکانس ساعت در شرایط محیطی و دمایی مختلف بسیار دقیق می باشد ، اما قیمت بالاتری دارد . هر دو ماژول در بخش های ساعت و تاریخ دارای آدرس های رجیستر یکسانی می باشند ، بنابراین در این پروژه از هر دوی ماژول ها می توان استفاده نمود و ساعت بدون مشکل کار خواهد کرد .
سخت ترین بخش ساخت پروژه ساعت دیجیتال بر روی سون سگمنت ، بخش تنظیم ساعت می باشد . در این پروژه ما از دو عدد سوییچ برای تنظیم ساعت و دقیقه استفاده می کنیم .
یک سوییچ جهت انتخاب بخش ساعت یا دقیقه می باشد به این صورت که اگر یکبار فشرده شود بخش ساعت انتخاب شده و اگر دو بار فشرده شود بخش دقیقه انتخاب می شود و بخش انتخاب شده به صورت چشمک زن در می آید .
در این حالت با هر بار فشردن سوییچ دوم بخش انتخاب شده یک واحد افزایش می یابد . اگر به مدت 5 ثانیه هیچ سوییچی فشرده نشود ، بخش انتخاب شده از حالت انتخاب شده خارج می شود و دیگر چشمک نمی زند .
سایت میکرونیک پروژه ساعت دیجیتال بر روی سون سگمنت را برای علاقه مندان به آردوینو – کدویژن – stm32 آماده کرده است که در انتهای همین صفحه می توانید این پروژه را تهیه نمایید .
پروژه ساعت دیجیتال روی سون سگمنت با آردوینو بر روی بورد arduino uno تست شده و به همراه این پروژه همه کتابخانه مورد نیاز به همراه شماتیک موجود می باشد .
پروژه ساعت دیجیتال روی سون سگمنت با stm32 بر روی بورد blue pill مبتنی بر میکروکنترلر stm32f103c8t6 تست شده است . تمامی کتابخانه های مورد نیاز به همراه شماتیک همراه پروژه موجود می باشد .
تمامی تنظیمات پروژه توسط نرم افزار STM32CubeMX انجام می شود .
این پروژه به صورت جداگانه برای نرم افزارهای keil , stm32cubeide ارائه شده است .
فیلم زیر نحوه عملکرد پروژه می باشد و پروژه های آردوینو و کدویژن نیز همین خروجی و عملکرد را دارند .
همچنین بخوانید >> پروژه ساعت دیجیتال با ماژول rtc ds3231 بر روی lcd کاراکتری + نمایش تاریخ شمسی + نمایش روزهای هفته + قابلیت تنظیم
همچنین بخوانید >> پروژه ساعت دیجیتال با ماژول تابلو روان max7219 + قابلیت تنظیم
نویسنده : حسین غیاثوند
ساعت دیجیتال با rtc داخلی avr : دانلود رایگان
ساعت دیجیتال بر روی سون سگمنت با ماژول tm1637 و ماژول ساعت ds1307 , ds3231 :