طرز کار ماژول سنسور تشخیص رنگ به اینصورته که نسبت به هر رنگ، فرکانس متفاوتی رو در پایه ی OUT ایجاد میکنه که با استفاده ازین فرکانس تولیدی رنگ اجسام رو تشخیص میدهیم.
سنسور تشخیص رنگ
ماژول تشخیص رنگ 8 پایه داشته که پایه ی VDD به پایانه مثبت و پایه GND به زمین و OE که پایه ی فعال ساز و active low بوده و برای استفاده باید به زمین وصل بشه.همچنین چهار پایه کنترلی S0 و S1 و S2 و S3 هستند که با صفر و یک کردن این پایه ها،برای تشخیص قرمز و آبی و سبز بودن و اسکیل بندی فرکانس خروجی از سنسور استفاده میشه.
تو این پروژه پایه های S2 و S3رو به پایه های B.0 و B.1 میکروکنترلر ATmega16 وصل میکنیم و طبق جدول بالا با صفر و یک کردن خروجی های B.0 و B.1 این سه رنگ رو به ترتیب انتخاب میکنیم و برای هر کدام از حالات،فرکانس خروجی رو حساب میکنیم.
DDRB.0=1;
DDRB.1=1;
فرکانس خروجی هم به این صورت محاسبه میشه که تعداد کلاک ها (تعداد یک شدن و یا صفر شدن) رو در زمان تعیین شده میشمارییم.زمان تعیین شده بسته به کاربردمون متفاوته،مثلا اگه بخواییم از سنسور تشخیص رنگ تو ربات مسیریاب استفاده کنیم از اون جاییکه زمان برایمان مهمه و باید در کمترین زمان ممکن رنگ رو تشخیص بده برای همین بازه ی زمانیمونو کوچکتر در نظر میگیریم که تو این پروژه قراره سنسور تشخیص رنگ در عرض 5.11میلی ثانیه،رنگ رو تشخیص بده.
[vc_row][vc_column][vc_text_separator title=”فروشگاه اینترنتی قطعات الکترونیک – AllElectronics.ir” color=”green” border_width=”3″ css=”.vc_custom_1505852473191{margin-bottom: 10px !important;}”][/vc_column][/vc_row][vc_row][vc_column width=”1/2″][vc_column_text css=”.vc_custom_1505852244591{margin-bottom: 10px !important;}”]
ماژول تشخیص رنگ TCS3200
120000 ریال
[/vc_column_text][vc_btn title=”خرید محصول” color=”green” size=”sm” align=”center” link=”url:http%3A%2F%2Fallelectronics.ir%2F%25D9%2586%25D9%2588%25D8%25B1-%25D9%2588-%25D8%25B1%25D9%2586%25DA%25AF%2F893-%25D9%2585%25D8%25A7%25DA%2598%25D9%2588%25D9%2584-%25D8%25AA%25D8%25B4%25D8%25AE%25DB%258C%25D8%25B5-%25D8%25B1%25D9%2586%25DA%25AF-tcs3200.html|title:%D8%AE%D8%B1%DB%8C%D8%AF%20%D8%B3%D9%86%D8%B3%D9%88%D8%B1%20%D8%B1%D9%86%DA%AF|target:%20_blank|” css=”.vc_custom_1505852203686{margin-top: 0px !important;}”][/vc_column][vc_column width=”1/2″][vc_column_text css=”.vc_custom_1505852226797{margin-bottom: 10px !important;}”]
سنسور رنگ TCS3200
95000 ریال
[/vc_column_text][vc_btn title=”خرید محصول” color=”green” size=”sm” align=”center” link=”url:http%3A%2F%2Fallelectronics.ir%2F%25D9%2586%25D9%2588%25D8%25B1-%25D9%2588-%25D8%25B1%25D9%2586%25DA%25AF%2F1149-%25D8%25B3%25D9%2586%25D8%25B3%25D9%2588%25D8%25B1-%25D8%25AA%25D8%25B4%25D8%25AE%25DB%258C%25D8%25B5-%25D8%25B1%25D9%2586%25DA%25AF-tcs3200d.html|title:%D8%AE%D8%B1%DB%8C%D8%AF%20%D8%B3%D9%86%D8%B3%D9%88%D8%B1%20%D8%B1%D9%86%DA%AF|target:%20_blank|” css=”.vc_custom_1505852174197{margin-top: 0px !important;}”][/vc_column][/vc_row][vc_row][vc_column][vc_separator color=”green” border_width=”3″][/vc_column][/vc_row]
برای شمارش کلاک ها از اینتراپت صفر استفاده میکنم که این پایه رو حساس به لبه ی پایین رونده در نظر میگیرم و برای این کار هم باید مدار پول آپ داخلی فعال بشه.در ضمن این پایه چون که قراره تعداد کلاک هارو بشمره باید بعنوان پایه ورودی تنظیم بشه.
DDRD.2=0;
PORTD.2=1;
برای فعال سازی اینتراپت صفر، بیت ششم رجیستر GICR رو یک میکنیم تا int0 فعال بشه.
GICR = 0X40;
در رجیستر GICR بجز بیت ششم با بقیه بیت ها کاری نداریم و هر چه باشد برایمان مهم نیست برای همین از عملگر | استفاده میکنیم البته دستور بالا مشکلی نداره ولی بهتره از دستور پایینی استفاده کنین.
GICR | = 0X40;
ازین عملگر زمانی که بخواهیم بیتی حتمن صفر باشه استفاده میکنیم.
نکته:عملگر & هم زمانی کاربرد داره که بخواییم بیتی،یک بمونه و بقیه بیت ها صفر باشه ولی عملگر | زمانیه که بخواییم بیتی یک باشه و با بقیه بیت ها کاری نداشته باشیم و هرچه که قبلن بود،بموونه.
GICR & = 0X40;
برای اینکه int0 اتفاق بیفته باید پرچم مربوطه اش رو در رجیستر GIFR صفر کنیم.توضیح کلیش به این صورته که هنگامی که وقفه ایی انجام بشه،پرچم مربوطه اش یک میشه،در این حالت وقفه اتفاق نمیفته و برای اینکه دوباره رخ بده باید پرچمش صفر بشه و برای صفر کردن پرچم توسط کدنویسی باید به پرچم یک بدیم تا اون صفر بشه.
GIFR = 0X40;
چون پایه ی int0(D.2)رو پول آپ کردیم،برای اینکه بتونیم کلاک هارو بشمریم باید کلاک حساس به لبه رو انتخاب کنیم که در اینجا حساس به لبه پایین رونده رو با دستور زیر تنظیم کردم.
MCUCR=0x02;
[ads1]
خب تا اینجا کدنویسی int0 رو برای شمارش کلاک ها انجام دادیم،برای تعیین زمان از تایمرکانترها استفاده میکنیم به این صورت که میخوام در عرض 5.11 میلی ثانیه تعداد کلاک هارو بشماره ولی چون فرکانس کاری میکرو رو 8 مگ انتخاب کرده ام برای همین،از مقسم فرکانسی 1024 استفاده میکنیم که این کار هم با توجه به آموزش تایمر کانترها ،توسط بیت های CS00 و CS01 و CS02 در رجیستر TCCR0 میسر میشه(از تایمرصفر استفاده میکنیم).
8000000/1024=7813 Hz
همانطوری که تناسب بالا نشون میده برای ایجاد زمان 5.11 میلی ثانیه به 40 تا کلاک سی پی یو نیاز داریم،برای همین مقدار رجیستر TCNT0 رو برابر صفر و مقدار رجیستر OCR0 رو 39 قرار میدم تا با هرچهل بار شمارش وقفه تطابق مقایسه(CTC)رخ بده و دستورات مورد نظر رو انجام بده(عدد 39رو در کدنویسی در مبنای هگزا مینویسیم که مقدار هگز آن 47میشه).
و همچنین برای استفاده از تطابق مقایسه باید در رجیستر TCCR0،اونو فعال کنیم که طبق دیتاشیت باید WGM01=1 و WGM00=0 .در کل برای این رجیستر مقدار زیر رو قرار میدیم:
TCCR0=0X0D;
اگه تایمر کانتر در مد CTC تنظیم شده باشه در آنصورت هر وقت که مقدار رجیستر TCNT0 و رجیسترOCR0 با هم برابر بشه،تایمر سرریز میشه و مقدار رجیستر TCNT0،صفر میشه و اگه وقفه تطابق مقایسه فعال باشه،در این حالت میتونیم دستوراتی تو این وقفه بنویسیم تا در زمان اورفلو رول سرویس وقفه انجام بشه.برای فعال سازی وقفه تطابق مقایسه بیت OCF0 رو یک میکنیم که این بیت در رجیستر TIMSK قرار داره:
TIMSK = 0X02;
[ads1]
تا این قسمت هم تونستیم تایمر صفر رو فعال کنیم و تنظیمات مربوطشو نیز انجام بدیم که البته همه ی این کارهارو میتونستیم با کدویزارد انجام بدیم ولی بهتره به کدنویسی نیز مسلط باشیم.
لازم به ذکره که تا الان فقط تونستیم int0 و timer0 رو فعال کنیم اما برای راه اندازی کامل به یه دستور دیگه ایی نیاز داریم:
#asm (“sei”)
برای اینکه فرکانس اندازه گرفته شده کمی دقیقتر باشه برای همین فعلن این دستور رو نمینویسیم تا تایمر و int0 شروع به کار نکنه، در ادامه با این دستور بیشتر کار میکنیم.
همان طوری که در بالا گفته شد،برای تشخیص قرمزی ،آبی یا سبزی بودن به S2 و S3 مقدارهای مربوطشو میدیم و با توجه به اینکه B.0 رو به S2 و B.1 رو به S3 وصل کرده ایم،با یک و صفر کردن پایه های B.0 و B.1 ، رنگ اجسام رو سنس میکنیم.
خب روند ادامه کار بعد از فعال سازیint0 و timer0 به این صورته که وارد حلقه ی while(1) شده و بعدش دستور
r_color = color_sensor_get_RGB(‘R’);
رو اجرا میکنه که با این دستور،کلاس color_sensor_get_RGB اجرا میکنه و آرگومان R که قرمز بودنو مشخص میکنه،به کلاس میفرسته.در داخل کلاس به شرط R رفته و پایه های B.0=0 و B.1=0 میکنه.بعدِ این دستور،وقفه ی عمومی فعال شده که طبق این دستور،تایمر صفر و int0 شروع به کار میکنه.
if(color_sensor_RGB == ‘R’)
{
PORTB.0=0; //S2
PORTB.1=0; //S3
}
#asm(“sei”)
while(!end_task);
دستور while بالایی با هدف منتظر نگه داشتن برنامه به کار برده شده تا رجیسترTCNT0 به مقدار رجیستر OCR0 برسه و تطابق مقایسه انجام بگیره به این صورت که مقدار اولیه end_task برابر صفر بوده که این صفر نات (not) شده و while(1) خواهیم داشت که همانطور که گفته شد،برنامه تو این شرط منتظر اجرای interrupt [TIM0_COMP] میمونه و هنگامی که این وقفه انجام میشه،end_task یک میشه و نات(not) آن صفر شده و while(0) خواهیم داشت که بلافاصله ازین حصر خارج میشه و برنامه بقیه دستوراتشو انجام میده.
البته در این حین با آمدن هر کلاک از پایه ی OUT سنسور تشخیص رنگ ، توسط int0 شمرده میشه.
[ads1]
هنگامی که مقدارTCNT0 به 40 برسه،وقفه ی تطابق مقایسه انجام میشه و چون set_point صفره،نات این مقدار یک شده و وارد if میشه و مقدار clk_counter که مقدار اولیه برای شمارش کلاکه رو صفر میکنه،همچنین در اینجا مقدار set_point رو یک میکنه تا بار دیگری که وقفه تطابق مقایسه انجام میگیره،وارد else بشه.
در همین حین،توسط int0 تعداد پالس ها شمرده میشه که باز در نهایت وقفه تطابق مقایسه رخ داده و چون set_point برابره یک هستش،وارد else میشه که مقدار شمارش شده رو (clk_counter) رو تو متغیر get_data ذخیره میکنه و با دستور
#asm (“cli”)
هم 0int و هم timer0 رو غیرفعال میکنه و end_task رو برابر یک قرار میده تا دستور while(!end_task) شکسته بشه و اطلاعاتی که بدست آمده(تعداد پالسها/get_data) رو برای پردازش های بعدی با دستور
return get_data;
به داخل while(1) برگرده و تو متغیر r_color ریخته بشه.
[ads1]
این فرایندی که تا الان انجام شد،فقط برای تشخیص میزان قرمزی اجسام بوده که این کار دو بار دیگر برای تشخیص میزان سبزی و آبی بودن نیز به کار میره و در متغیر های مربوطه اش ذخیره میشه. سنسور تشخیص رنگ
بعد از انجام هر سه مرحله فوق و بدست آمدن مقدار متغیر های r_color و g_color و b_color ،این متغیرها توسط تابع sprintf تو متغیر بافر که از نوع کاراکتر رشته ایه ذخیره میشه تا بتونه تو خروجی چاپ بشه(ال سی دی تنها میتونه رشته ایی از کارکترها رو چاپ کنه) که بصورت زیر عمل میکنیم.
نکته:تابع sprint در کتابخانه ی stdio قرار داره.
#include <stdio.h>
[ads1]
حالا تو این قسمت میاییم و سنسور تشخیص رنگ رو جلوی اجسام رنگی قرار میدیم و مقدار عدد نمایش داده شده به ازای هر رنگ رو بدست میاریییم،بعد بازه ایی شامل اون عدد رو در شروط if قرار میدیم تا در خروجی نام رنگ رو چاپ کنه.این نکته هم فراموش نشه که ما ابتدا با چهار خط بالا رو به میکرو پروگرام میکنیم و عدد هارو یادداشت میکنیم بعد این چهارخط رو حذف کرده و کد های زیر رو جایگزین میکنیم.
[ads1]
این عدد های که در شرط ها نوشتم،همش با آزمون و خطا بدست اومده که برای پیدا کردن این اعداد،مقدار اسکیل رو 20درصد قرار دادم که طبق دیتاشیت سنسور تشخیص رنگ ، برای این کار S0 رو به VCC و S1 رو به GND وصل کرده ام.
#include <mega16a.h> #include <alcd.h> #include <stdio.h> #include <delay.h> //char buffer[16]; unsigned char clk_counter; unsigned char get_data; bit set_point; bit end_task; char color_sensor_get_RGB(char color_sensor_RGB) { if(color_sensor_RGB == 'R') { PORTB.0=0; //S2 PORTB.1=0; //S3 } else if(color_sensor_RGB == 'G') { PORTB.0=1; //S2 PORTB.1=1; //S3 } else if(color_sensor_RGB == 'B') { PORTB.0=0; //S2 PORTB.1=1; //S3 } #asm("sei") while(!end_task); #asm("cli") end_task = 0; // GICR = 0x00; // int0 disable // GIFR = 0x00; //int0 flag is 1 // TCCR0 = 0x00; //timer0 disable return get_data; } interrupt [EXT_INT0] void ext_int0_isr(void) { clk_counter++; } interrupt [TIM0_COMP] void timer0_comp_isr(void) { if(!set_point) { clk_counter = 0; end_task = 0; set_point = 1; #asm("sei") //public interrupt Enable } else { get_data = clk_counter; end_task = 1; set_point = 0 ; #asm("cli") //public interrupt disable } } void main(void) { int r_color=0 ,g_color =0 ,b_color=0; lcd_init(16); //color_sensor_init set_point = 0; clk_counter =0; end_task = 0; DDRB.0 = 1; // S2 DDRB.1 = 1; // s3 DDRD.2=0; // OUT PORTD.2=1; // pull up GICR |= 0x40; // int0 interrupt Enable GIFR = 0x40; // int0 interrupt flag MCUCR=0x02; // Falling TCNT0=0x00; //Bottom value OCR0=0x27; //in Dec is 40 TCCR0 = 0x0D; //00001101 CTC mode & prescale:1024=>frequency=7813 Hz,5.11ms TIMSK=0x02; //compare interrupt while (1) { r_color = color_sensor_get_RGB('R'); g_color = color_sensor_get_RGB('G'); b_color = color_sensor_get_RGB('B'); if (r_color>80 && r_color<130 && g_color>50 && g_color<100 && b_color>230 && b_color<280) { lcd_clear(); lcd_puts("white"); } else if ( r_color>40 && r_color<90 && g_color>30 && g_color<90 && b_color>30 &&b_color<90) { lcd_clear(); lcd_puts("black"); } else if (r_color>90 && r_color<170 && g_color>0 && g_color<20 && b_color>20 && b_color<80) { lcd_clear(); lcd_puts("blue"); } else if (r_color>140 && r_color<210 && g_color>80 && g_color<120 && b_color>90 && b_color<150) { lcd_clear(); lcd_puts("red"); } else if (r_color>180 && r_color<230 && g_color>210 && g_color<270 && b_color>200 && b_color<270) { lcd_clear(); lcd_puts("orange"); } // sprintf(buffer,"R:%d G:%d B:%d",r_color,g_color,b_color); // lcd_clear(); // lcd_puts(buffer); delay_ms(100); } }
دیدگاهتان را بنویسید