معماری

سنسور تشخیص رنگ TCS3200 با AVR

طرز کار ماژول سنسور تشخیص رنگ به اینصورته که نسبت به هر رنگ، فرکانس متفاوتی رو در پایه ی OUT  ایجاد میکنه که با استفاده ازین فرکانس تولیدی رنگ اجسام رو تشخیص میدهیم.

سنسور تشخیص رنگ

ماژول تشخیص رنگ ۸ پایه داشته که پایه ی 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;

فرکانس خروجی هم به این صورت محاسبه میشه که تعداد کلاک ها (تعداد یک شدن و یا صفر شدن) رو در زمان تعیین شده میشمارییم.زمان تعیین شده بسته به کاربردمون متفاوته،مثلا اگه بخواییم از سنسور تشخیص رنگ تو ربات مسیریاب استفاده کنیم از اون جاییکه زمان برایمان مهمه و باید در کمترین زمان ممکن رنگ رو تشخیص بده برای همین بازه ی زمانیمونو کوچکتر در نظر میگیریم که تو این پروژه قراره سنسور تشخیص رنگ در عرض ۵٫۱۱میلی ثانیه،رنگ رو تشخیص بده.

فروشگاه اینترنتی قطعات الکترونیک - AllElectronics.ir

برای شمارش کلاک ها از اینتراپت صفر استفاده میکنم که این پایه رو حساس به لبه ی پایین رونده در نظر میگیرم و برای این کار هم باید مدار پول آپ داخلی فعال بشه.در ضمن این پایه چون که قراره تعداد کلاک هارو بشمره باید بعنوان پایه ورودی تنظیم بشه.

DDRD.2=0;

PORTD.2=1;

برای فعال سازی اینتراپت صفر، بیت ششم رجیستر GICR رو یک میکنیم تا int0 فعال بشه.

GICR = 0X40;

در رجیستر GICR بجز بیت ششم با بقیه بیت ها کاری نداریم و هر چه باشد برایمان مهم نیست برای همین از عملگر | استفاده میکنیم البته دستور بالا مشکلی نداره ولی بهتره از دستور پایینی  استفاده کنین.

GICR | = 0X40;

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

نکته:عملگر & هم زمانی کاربرد داره که بخواییم بیتی،یک بمونه و بقیه بیت ها صفر باشه ولی عملگر | زمانیه که بخواییم بیتی یک باشه و با بقیه بیت ها کاری نداشته باشیم و هرچه که قبلن بود،بموونه.

GICR & = 0X40;

برای اینکه int0 اتفاق بیفته باید پرچم مربوطه اش رو در رجیستر GIFR صفر کنیم.توضیح کلیش به این صورته که هنگامی که وقفه ایی انجام بشه،پرچم مربوطه اش یک میشه،در این حالت وقفه اتفاق نمیفته و برای اینکه دوباره رخ بده باید پرچمش صفر بشه و برای صفر کردن پرچم توسط کدنویسی باید به پرچم یک بدیم تا اون صفر بشه.

GIFR = 0X40;

چون پایه ی int0(D.2)رو پول آپ کردیم،برای اینکه بتونیم کلاک هارو بشمریم باید کلاک حساس به لبه رو انتخاب کنیم که در اینجا حساس به لبه پایین رونده رو با دستور زیر تنظیم کردم.

MCUCR=0x02;

رجیستر DDR و PORT و وقفه

خب تا اینجا کدنویسی int0 رو برای شمارش کلاک ها انجام دادیم،برای تعیین زمان از تایمرکانترها استفاده میکنیم به این صورت که میخوام در عرض ۵٫۱۱ میلی ثانیه تعداد کلاک هارو بشماره ولی چون فرکانس کاری میکرو رو ۸ مگ انتخاب کرده ام برای همین،از مقسم فرکانسی ۱۰۲۴ استفاده میکنیم که این کار هم با توجه به آموزش تایمر کانترها ،توسط بیت های CS00 و CS01 و CS02 در رجیستر TCCR0 میسر  میشه(از تایمرصفر استفاده میکنیم).

۸۰۰۰۰۰۰/۱۰۲۴=۷۸۱۳   Hz

همانطوری که تناسب بالا نشون میده برای ایجاد زمان ۵٫۱۱ میلی ثانیه به ۴۰ تا کلاک سی پی یو نیاز داریم،برای همین مقدار رجیستر  TCNT0 رو برابر صفر و مقدار رجیستر OCR0 رو ۳۹ قرار میدم تا با هرچهل بار شمارش وقفه تطابق مقایسه(CTC)رخ بده و دستورات مورد نظر رو انجام بده(عدد ۳۹رو در کدنویسی  در مبنای هگزا  مینویسیم که مقدار هگز آن ۴۷میشه).

و همچنین برای استفاده از تطابق مقایسه باید در رجیستر TCCR0،اونو فعال کنیم که طبق دیتاشیت باید WGM01=1 و WGM00=0 .در کل برای  این رجیستر مقدار زیر رو قرار میدیم:

TCCR0=0X0D;

اگه تایمر کانتر در مد CTC تنظیم شده باشه در آنصورت هر وقت که مقدار رجیستر TCNT0 و رجیسترOCR0 با هم برابر بشه،تایمر سرریز میشه و مقدار رجیستر TCNT0،صفر میشه و اگه وقفه تطابق مقایسه فعال باشه،در این حالت میتونیم دستوراتی  تو این وقفه بنویسیم تا در زمان اورفلو رول سرویس وقفه انجام بشه.برای فعال سازی وقفه تطابق مقایسه  بیت OCF0 رو یک میکنیم که این بیت در رجیستر TIMSK قرار داره:

TIMSK = 0X02;

تایمر کانتر صفر

تا این قسمت هم تونستیم تایمر صفر رو فعال کنیم و تنظیمات مربوطشو نیز انجام بدیم که البته همه ی این کارهارو میتونستیم با کدویزارد انجام بدیم ولی بهتره به کدنویسی نیز مسلط باشیم.

لازم به ذکره که تا الان فقط تونستیم 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 شمرده میشه.

وقفه int0 سابروتین

هنگامی که مقدارTCNT0 به ۴۰ برسه،وقفه ی تطابق مقایسه انجام میشه و چون set_point صفره،نات این مقدار یک شده و وارد if میشه و مقدار clk_counter که مقدار اولیه برای شمارش کلاکه رو صفر میکنه،همچنین در اینجا مقدار set_point رو یک میکنه تا بار دیگری که وقفه تطابق مقایسه انجام میگیره،وارد else بشه.

سورس کد زبان C++

در همین حین،توسط int0 تعداد پالس ها شمرده میشه که باز در نهایت وقفه تطابق مقایسه رخ داده و چون set_point برابره یک هستش،وارد else میشه که مقدار شمارش شده رو (clk_counter) رو تو متغیر get_data ذخیره میکنه و با دستور

#asm (“cli”)

هم ۰int و هم timer0 رو غیرفعال میکنه و end_task رو برابر یک  قرار میده تا دستور while(!end_task) شکسته بشه و اطلاعاتی که بدست آمده(تعداد پالسها/get_data) رو برای پردازش های بعدی با دستور

return get_data;

به داخل while(1) برگرده و تو متغیر r_color ریخته بشه.

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

وقفه تطابق مقایسه با تایمر صفر timer0

این فرایندی که تا الان انجام شد،فقط برای تشخیص میزان قرمزی اجسام بوده که این کار دو بار دیگر  برای تشخیص میزان سبزی و آبی بودن نیز به کار میره و در متغیر های مربوطه اش ذخیره میشه. سنسور تشخیص رنگ

فراخوانی تابع در avr و c

بعد از انجام هر سه مرحله فوق و بدست آمدن مقدار متغیر های r_color و g_color و b_color ،این متغیرها توسط تابع sprintf تو متغیر بافر که از نوع کاراکتر رشته ایه ذخیره میشه تا بتونه تو خروجی چاپ بشه(ال سی دی تنها میتونه رشته ایی از کارکترها رو چاپ کنه) که بصورت زیر عمل میکنیم.

نکته:تابع sprint در کتابخانه ی stdio قرار داره.

#include <stdio.h>

سورس کد تابع sprintf ککتابخانه stdio

حالا تو این قسمت میاییم و سنسور تشخیص رنگ رو جلوی اجسام رنگی قرار میدیم و مقدار عدد نمایش داده شده به ازای هر رنگ رو بدست میاریییم،بعد بازه ایی شامل اون عدد رو در شروط if قرار میدیم تا در خروجی  نام رنگ رو چاپ کنه.این نکته هم فراموش نشه که ما ابتدا با چهار خط بالا رو به میکرو پروگرام میکنیم و عدد هارو یادداشت میکنیم بعد این چهارخط رو حذف کرده و کد های زیر رو جایگزین میکنیم.

ماژول تشخیص رنگ TCS3200 سورس کد

این عدد های که در شرط ها نوشتم،همش با آزمون و خطا بدست اومده که برای پیدا کردن این اعداد،مقدار اسکیل رو ۲۰درصد قرار دادم که طبق  دیتاشیت سنسور تشخیص رنگ ، برای این کار 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);
}
}

 

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

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

قالب وردپرس