الکترونیک، رباتیک و مکانیک

آموزش به زبان بسیار ساده و روان (از صفر تا بینهایت)

الکترونیک، رباتیک و مکانیک

آموزش به زبان بسیار ساده و روان (از صفر تا بینهایت)

الکترونیک، رباتیک و مکانیک

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

نویسندگان
پیوندهای روزانه
طبقه بندی موضوعی
آخرین نظرات

پنجشنبه, ۳ دی ۱۳۹۴، ۱۰:۵۱ ق.ظ

۱

 

 

دومین قسمت از آموزش برنامه نویسی،تحت عنوان "کار با واحد ADC" رو مورد ارزیابی قرار می دهیم.

 

پس با ما در ادامه مطلب همراه باشید...

 

به نام خدا

سلام ...

حالتون چطوره ؟!

خوب هستید ؟

بزارید اول تشکر کنم از اون دسته از دوستانی که با نظراتشون به بنده دلگرمی میدند و لطف دارند !

و البته گله کنم از اونایی که بی تفاوت از کنار مطالب رد میشند.عزیزم نظر بزار ...

اون زمانی که این وبلاگ رو راه انداختم نمیدونستم دقیقا میخوام چقدر مطلب بزارم و کلا تا چه سطحی پیش برم.اما همونطور که میبینید بخش 18 آموزش رو هم شروع کردیم و با دعای خیر شما دوستان ایشالا میریم تا بخش  1018 !!! cheeky

خوشحال میشم بتونم روز به روز هم خودم پیشرفت کنم،هم شما پیشرفت کنید و هم وبلاگ پیشرفت کنه !

بنابر این شما هم اگه کمکی از دستتون برمیاد،کوتاهی نکنید و اگه نظری دارید و یا میتونید به طریقی مدد کنید،منتظر یاری سبزتان هستم ...


اما برنامه امروزمون چیه برای آموزش ؟!

قراره یه دماسنج دیجیتال بسازیم که درجه دما رو به سانتیگراد بر روی سون سگمنت نمایش بده.

 

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

 

1.میکروکنترلر ATmega32 ==> یک عدد

2.سنسور LM35DZ ==> یک عدد

3.سون سگمنت مالتی پلکس 4 تایی آند مشترک==> یک عدد  ==> البته میتونید سون سگمنت دوتایی تا چهارتایی،بسته به نیازتون انتخاب کنید.

4.منبع تغذیه 5 ولت

5.سیم رابط ==> به مقدار لازم Laughing

 

پس :

اول از همه یه توضیحی میدم راجع به سنسور LM35.

بعد از اون،به کانفیگ کردن رجیستر های واحد ADC میپردازیم.

بعدش یاد میگیریم که چجوری با سون سگمنت کار کنیم.

و در پایان یه دماسنج توپ خواهیم داشت !!!

 

توجه داشته باشید که در برنامه کاری وبلاگ به هیچ عنوان پروژه محوری نبوده و نیست.

ولی برای اینکه مطالب بهتر جا بیفته،لازمه که در قالب یه پروژه بحث رو پیش ببریم ...

 

در مورد اینکه چرا ساخت دماسنج با LM35 رو بعنوان صورت مسئله این بخش در نظر گرفتم میتونم بگم که ؛ کار با LM35 راحته و همچنین اغلب مدرسان AVR و همچنین کتابها و کلاسهای آموزشی تا به بحث آموزش AVR میرسند،غیر ممکنه که کار با LM35 رو بعنوان پروژه این بخش مطرح نکنند !!!

 

پس هیچ احدالناسی نمیتونه من و شما رو مجبور کنه که با چه المانی کار کنید؛بنده عشقم کشیده با LM35 کار کنم ! مشکلیه ؟!!! Tongue Out



سنسور دمای LM35 :

 

همونطور که میبینید،این سنسور ظاهر عجیب و غریبی نداره و از همون رده BJT های خودمونه !

 

قصد ندارم بصورت جامع در مورد این سنسور بنویسم،ولی یه سری خصوصیاتش رو بصورت تیتر وار میگم خدمتتون :
 

1.این سنسور به ازای هر درجه سانتی گراد افزایش دما،10 میلی ولت به خروجی خودش اضافه میکنه.
2.دارای حداکثر خطای 0.5 درجه سانتی گراد است.

3.سه پایه با نام های Vc , GND , Vout داره،که مقدار Vc میتونه در رنج 4 تا 30 ولت باشه که معمولا از ولتاژ های معمول 5 ولت و 12 ولت استفاده میشه !
4.قابلیت اندازه گیری دما در محدوده +150 تا -150 رو داره.

 

اطلاعات بیشتر خواستید،میتونید دیتاشیت این قطعه رو از ستون سمت چپ وبلاگ در بخش "مستندات" بیابید و دانلود کنید و بخوانید !

 

اما توضیحات ساده این سنسور به زبون تخصصی خودم cheeky :
 

عزیزم heart

این قطعه که میبینید یه سنسوره که برای اندازه گیری دما ازش استفاده میشه !

روش کارش اینطوریه که با هر درجه سانتی گراد افزایش دما،10 میلی ولت میندازه روی پایه Vout !

مثلا اگه الان دمای محیط 20 درجه سانتی گراد باشه،مقدار 200 میلی ولت از پایه Vout دریافت خواهیم کرد.(هر درجه،10 میلی ولت !)

 

اینم از ترتیب و اسم پایه ها :


یجور دیگه اگه بخوایم مساله رو عنوان کنیم میتونیم بگیم که قصد داریم یه ولتمتر بسازیم !!! (نه ؟!)

بریم سراغ برنامه نویسی و مقدار دهی رجیسترها :

 

فرکانس کاری میکروکنترلر را 8 مگاهرتز در نظر میگیریم.

#include <mega32.h>
#include <delay.h>

void adc_configuration(){}
unsigned int temp(){}
void main(){}

 

دو تا تابع تعریف میکنیم با نام های : adc_configuration و temp .(توجه : انتخاب نام توابع کاملا اختیاری است.)

در تابع adc_configuration تنظیمات پیکربندی واحد ADC رو انجام میدیم.

تابع temp هم وظیفه قرائت مقدار دما رو داره.

 

اول شروع میکنیم به کانفیگ کردن واحد ADC ؛ یعنی نوشتن تابع adc_configuration بصورت گام به گام :

 

رجیستری داشتیم با نام ؛ ADMUX :

کانال مورد نظر ما ADC0 هست و ولتاژ مرجعمون رو هم به دلخواه روی 2.56 ولت داخلی قرار میدیم :

 

void adc_configuration(){
ADMUX |= (1<<REFS1)|(1<<REFS0);
}

 

 

رجیستر دیگه ای هم بود با نام ؛ ADCSRA :

ضریب تقسیم رو 64 میگیریم و فلگ ADEN رو هم یک میکنیم تا واحد ADC فعال بشه :

void adc_configuration(){
ADMUX |= (1<<REFS1)|(1<<REFS0);
ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADEN);
} 

تا اینجا پیکربندی ADC تموم شد.

 

تابع بعدی که مورد بحثمونه،تابع تعریفیه temp ـه ! :

 

unsigned int temp(){}


کاری که باید در این قسمت انجام بدیم،اول از همه،فرمان برای شروع تبدیله ،که با یک کردن فلگ ADSC انجام میشه !

unsigned int temp(){
ADCSRA |=(1<<ADSC);
}

 

با صدور فرمان شروع تبدیل،باید منتظر بمونیم تا تبدیل انجام بشه و پس از پایان یافتن تبدیل،مقدار رجیستر ADC رو بخونیم !

 

حالا از کجا بفهمیم که تبدیل تموم شده ؟

قبلنا براتون گفتم که یه فلگی داریم با نام ADIF که اصل کارش همینه !

وقتی یک بشه،یعنی تبدیل تموم شده و وقتی صفر باشه یعنی واحد ADC در حال انجام عملیات تبدیله.

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

بعد هم که یک شد،با نوشتن یه یک دیگه روش دوباره صفرش میکنیم (جل الخالق laugh).

unsigned int temp(){
ADCSRA |=(1<<ADSC);
while ((ADCSRA & (1<<ADIF))==0);
ADCSRA |=(1<<ADIF);
}

 

الان دیگه تبدیل انجام شده و رجیسترهای ADCL و ADCH که وظیفه نگهداری مقدار ADC رو دارند،پر شدند و حاوی مقدار ADC هستند.

نکته ای که باید بگم اینه که به مجموع دو تا رجیستر ADCL و  ADCH میگند ADCW که در واقع قراره یه عدد 10 بیتی رو به ما تحویل بده ! (توضیحاتشو قبلن دادم.نکنه میخواین دوباره بگم ؟! surprise)

unsigned int temp(){
ADCSRA |=(1<<ADSC);
while ((ADCSRA & (1<<ADIF))==0);
ADCSRA |=(1<<ADIF);
return ADCW;
}

 

تا اینجای کار،دو تا تابع اصلیمون رو نوشتیم که وظیفه عملیات های واحد ADC رو بر عهده داشتند.

اما قرارمون این بود که مقدار دما رو بخونیم و روی سون سگمنت نمایش بدیم.

 

پس میریم سراغ ادامه آموزش و توضیح تابع اصلی main :

 

void main(){}

 

روند کار به این صورته که :

 

1.دما رو میخونیم.

2.داخل متغیری با نام T میریزیم.

3.چون دما چند رقمیه (اینجا دو رقم) باید تفکیک به دو عدد تک رقمی بشه.

4.اعداد تفکیک شده از آرایه مربوط به اعداد (seg) انتخاب میشند.

5.اعداد با یه تکنیک خاص روی سون سگمنت نمایش داده میشند.

 

الان میخوایم مقدار دما رو بخونیم :

 

مقدار برگردونده شده از تابع temp رو داخل متغیر T میریزیم.

با توجه به فرمولی که در بخش 12 آموزش های وبلاگ دادم بهتون،مقدار T جدید رو محاسبه میکنید.

این مقدار جدید،مساوی با اندازه دما در واحد درجه سلسیوس است.

لازم بذکره که دلیل اضافه شدن عبارت (100*) اینه که سنسور مقدار رو به میلی ولت به ما تحویل میده !

T = temp();
T = (((T*2.56)*100)/1023);

 

 

قبل از همه،اعداد مورد نظرمون رو برای نمایش رو سون سگمنت میسازیم.

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

 

برای راحتی کار،اعداد 0 تا 9 + علامت درجه + حرف C رو در قالب کد براتون آماده گذاشتم :

به نحوی که که عضو صفرم از آرایه seg معادل عدد 0 و عضو یکم معادل عدد 1 و ... و عضو دهم معادل علامت درجه و عضو یازدهم معادل حرف C .

(دقت کنید که شمارش اعضای آرایه از صفر شروع میشه).

 

کاتد مشترک :

unsigned char seg[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x63,0x39};

 

آند مشترک :

unsigned char seg[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x1C,0x46};

 

 

برای اینکه برنامه نویسیمون مرتب تر در بیاد،یه تابع دیگه هم تعریف میکنیم به اسم : seg_display و کلیه مسائل مربوط به نمایش سون سگمنت رو در اون انجام میدیم.

 

void seg_display (unsigned int temp){}

 

این تابع مقدار دما رو میگیره و با عملیاتی که روش انجام میده،برای نمایش روی سون سگمنت آمادش میکنه.

 

void seg_display (unsigned int temp){
    unsigned char seg[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x1C,0x46};
    unsigned char data[4];
    
    DDRB=0xFF;
    DDRD=0x0F;
    
    data[0]=seg[temp/10];
    data[1]=seg[temp%10];
    data[2]=seg[10];
    data[3]=seg[11];
    
    for (i = 0; i < 4; i++)
    {
     PORTB=data[i];
     PORTD=0x00;
     PORTD=1<<i;
     delay_us(500);
    }
}


ایندفعه یکباره همه کدهای تابع رو یه جا نوشتم تا بهتر متوجه بشید.

 

unsigned char data[4]; 

از این آرایه بعنوان یک بافر استفاده میکنیم که قراره مقادیری رو از آرایه seg در خودش بریزه !

 

DDRB=0xFF;
DDRD=0x0F; 

در این قسمت هم پورت B رو که بعنوان خطوط کنترلی abcdefg+dot سون سگمنت،استفاده شدند رو بعنوان خروجی و همچنین 4 پین اول پورت D رو بعنوان خروجی که در واقع خطوط کنترلی 1234 سون سگمنت ها هستند،انتخاب کردیم.

 

data[0]=seg[temp/10]; 

این قسمت به بعد رو خیلی خوب یاد بگیرید،چون برای کار با سون سگمنت بصورت کلیشه ای باید این کار ها رو همیشه انجام بدید.

 

فرض کنید که دمای اندازه گیری شده 27 درجه سانتی گراده و میخوایم روی سون سگمنت عدد رو نمایش بدیم.

عدد مورد نظر برای نمایش روی سون سگمنت بصورت کاملترش به این شکله :

27 °C

 

که تشکیل شده از عدد دهگان (2) و عدد یکان (7) و علامت ثابت (°) و حرف (C) !

اگر یادتون باشه،برای نمایش روی سون سگمنت باید بصورت تک تک اعداد رو روی هرکدوم از سون سگمنتها نمایش بدیم.

که اینجا سون سگمنت ما از نوع مالتی پلکس 4 تایی آند مشترکه !

پس باید روی سون سگمنت 1 عدد 2 - روی سون سگمنت 2 عدد 7 - روی سون سگمنت 3 علامت ° - روی سون سگمنت 4 حرف C نمایش داده بشه.

پس در اولین مرحله باید اعداد رو از هم تفکیک کنیم.

 

پس میریم یخورده ریاضیات پیش دبستانی رو با هم دوره میکنیم  laugh:

فرض کنید یه عددی مثل 1453 رو میخوایم اعدادشو از هم تفکیک کنیم.
عدد مورد نظر از : یکان-دهگان-صدگان-هزارگان تشکیل شده.
حالا اگه این عدد رو بر 1000 تقسیم کنیم،خارج قسمت میشه : 1 (هزارگان)
باقی ماندش هم میشه : 453
اگه 453 رو بر 100 تقسیم کنیم،خارج قسمت میشه : 4 (صدگان)
باقی مونده هم میشه : 53
اگه 53 رو بر 10 تقسیم کنیم،خارج قسمت میشه : 5 (دهگان)
باقی مونده هم میشه : 3 (یکان)

 

ما هم دقیقا از همین تکنیک برای تفکیک اعداد از همدیگه استفاده میکنیم !

ولی در این پروژه ای که ما روش کار میکنیم با اعداد 2 رقمی کار داریم پس کار ساده تر میشه !

 

data[0]=seg[temp/10];  

اینجا اومدیم و عدد دهگان رو با تقسیم عدد بر 10 مشخص کردیم،بعد مقدار متناظرش رو از آرایه seg انتخاب کردیم و اونو ریختیم در عضو صفرم آرایه data.

 

data[1]=seg[temp%10]; 

تو این مرحله باقی مانده عدد مورد نظرمون رو بر 10 که میشه همون یکان رو مشخص کردیم و مقدار متناظرش از آرایه seg هم انتخاب شده و در عضو یکم آرایه data ریخته شده.

 

تا این مرحله عدد دو رقمی رو با تفکیک به دوتا عدد تک رقمی تبدیل کردیم.

 

data[2]=seg[10];
data[3]=seg[11];

گفتیم که؛اعضای دهم و یازدهم آرایه seg علامت ° و حرف C رو شامل میشند که بصورت ثابت در خانه های 2 و 3 آرایه data قرار میگیرند.

 

از اینجا به بعد وظیفه ما نمایش اعضای : 0و1و2و3 آرایه data بر روی سون سگمنتهای 1و2و3و4 به ترتیبه .

 

for (i = 0; i < 4; i++)
{
PORTB=data[i];
PORTD=0x00;
PORTD=1<<i;
delay_us(500);
} 

اومدیم و یه حلقه ایجاد کردیم که طبق همون تکنیک اثر فلیکر با یه تاخیر 500 میکروثانیه ای،به ترتیب مقادیر سون سگمنتهای 1و2و3و4 رو نمایش بدیم.

 

PORTB=data[i]; 

اطلاعات مورد نمایش رو بر روی پورت B قرار میدیم.

 

PORTD=0x00;
PORTD=1<<i; 

از طریق این بخش پایه های کنترلی 1و2و3و4 سون سگمنت رو کنترل میکنیم.

 

بصورت خیلی خلاصه براتون توضیح میدم که چجوری 27 درجه سانتی گراد،روی سون سگمنت 4 تایی نمایش پیدا میکنه(باتوجه به کد نوشته شده) :

اول از همه میگیم که میخوایم عدد 2 رو نمایش بدیم.
بعدش انتخاب میکنیم که باید سون سگمنت 1 این عدد رو نمایش بده.
پس از اون باید عدد 7 رو نمایش بدیم.
اینجا هم بهش میگیم که باید سون سگمنت 2 مسئول نمایش این عدد باشه.
و به همین ترتیب برای علامت درجه و حرف C و همچنین سون سگمنتهای 2 و 3 !

 

اینم از شماتیک :

در پایان هم کل کدی که نوشته شده رو یه جا قرار میدم براتون :

#include <mega32.h>
#include <delay.h>

unsigned int i,T;

// ADC Configuration Function
void adc_configuration(){
    ADMUX |= (1<<REFS1)|(1<<REFS0);
    ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADEN);
}

// ADC Temprature Reading Function
unsigned int temp(){
    ADCSRA |=(1<<ADSC);
    while ((ADCSRA & (1<<ADIF))==0);
    ADCSRA |=(1<<ADIF);
    return ADCW;
}

// 7Seg Display Function
void seg_display(unsigned int temp){
    
    // Common Cathod 4-Digit 7Seg Display Code
    unsigned char seg[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x1C,0x46};
    unsigned char data[4];
    
    DDRB=0xFF;
    DDRD=0x0F;
    
    // Number Separating
    data[0]=seg[temp/10];
    data[1]=seg[temp%10];
    data[2]=seg[10];
    data[3]=seg[11];
    
    // Displaying Loop
    for (i = 0; i < 4; i++)
    {
     PORTB=data[i];
     PORTD=0x00;
     PORTD=1<<i;
     delay_us(500);
    }

}

// Main Function
int main(void)
{
    while(1)
    {
         adc_configuration();
         
         // Temprature Calculating
         T = temp();
         T=(T*256/1023);
         
         seg_display(T);     
         
    }
}

 

 توجه : اگه میخواین این پروژه رو عملی ببندید و ازش استفاده کنید قبلش مشکل جریان سون سگمنتها رو حل کنید !

 

 چون هدف ما اینجا ساخت پروژه نبود،بنده از توضیح اینکه چجوری مشکل جریان رو رفع کنیم،خودداری کردم.

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

 

اینم از قسمت دوم کارگاه عملی ...

نظر یادتون نره.

سوالی بود تو انجمن بپرسید.

 

فعلا...


منبع : www.noise.blog.ir

نظرات  (۱)

با سلام
تا درجه 31 را درست نشون میده ولی از 31 به بالا مشکل پیش میاد و اعداد  T عوض می شوند میشه دلیلشو بگین

ارسال نظر

ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی