در این آموزش به راه اندازی سنسور Flex با میکروکنترلر ATMEGA8 میپردازیم. برای این کار از ADC (مبدل آنالوگ به دیجیتال) 10 بیتی mega8 استفاده میکنیم. واحد ADC در mega8 حداکثر قادر به تحمل ولتاژ 5 ولت در ورودی خود است. در ادامه با ما همراه باشید.
سنسور خمشی چیست؟
Flex Sensor یا سنسور خمشی یک ترانسدیوسر است که با تغییر پیدا کردن شکل آن مقاومت دو سر آن نیز تغییر میکند. تصویر آن را در زیر میبینید.
از این سنسور برای تشخیص تغییرات در خطی بودن استفاده میشود. بنابراین وقتی سنسور خم میشود مقاومت آن به شدت بالا میرود که در تصویر زیر نشان داده شده است:
اکنون برای تبدیل این تغییرات مقاومت به تغییرات ولتاژ از یک مدار تقسیم مقاومتی استفاده میکنیم . در این شبکهی مقاومتی یک مقاومت ثابت و یک مقاومت متغییر داریم. با توجه به تصور زیر R1 در اینجا مقاومت ثابت و R2 سنسور خمشی است که به عنوان یک مقاومت متغییر عمل میکند. ولتاژ گره میانی این شبکه اندازه گیری میشود. با تغییر مقدار مقاومت R2 این ولتاژ نیز به طور خطی تغییر میکند. بنابراین ما یک ولتاژ داریم که با میزان خطی بودن تغییر میکند.
اکنون نکتهی مهمی که باید به آن توجه کنیم این است که ADC میکروکنترلر برای اندازه گیری ولتاژ ورودی جریانی در حدود 50میکروآمپر از آن میکشد. این اثر بارگذاری در یک مقسم ولتاژ مقاومتی اهمیت دارد زیرا با افزایش جریان کشیده شده از خروجی تقسیم مقاومتی درصد خطای اندازهگیری نیز افزایش پیدا میکند. البته ما در این آموزش از این خطا چشم پوشی میکنیم.
اکنون به دنبال مقاومتهایی هستیم که برای ولتاژ ورودی 25 ولت ولتاژ خروجی 5 ولت داشته باشیم. برای بدست آوردن مقدار واقعی ولتاژ نیز کافیست تا در برنامه مقدار ولتاژ خروجی سنسور را در 5 ضرب کنیم.
قطعات مورد نیاز راه اندازی سنسور Flex:
سخت افزار:
ATMEGA8، منبع تغذیه 5 ولت، پروگرامر AVR-ISP، ال سی دی 16×2، خازن 100میکروفاراد، خازن 100نانوفاراد (5عدد)، مقاومت 100کیلواهم.
نرم افزار:
Atmel studio 6.1 , progisp یا flash magic
شماتیک و نحوه کارکرد مدار
پورت D میکروکنترلر به خطوط دیتای LCD وصل شده است. lcd 16×2 در مجموع با پایههای بک لایت دارای 16 پایه است که 8 عدد از آنها مربوط به دیتا هستند (7-14یاD0-D7) 2 پایه برای تغذیه (1و2 یا VSSوVDD یا 5vوGND) پایه سوم برای تنظیم کنترل است (VEE) و 3 پایه برای کنترل (RS,RW,E) .
میتوانید در مدار مشاهده کنید که من فقط از 2 پایه کنترلی استفاده کردهام. پایههای کنتراست و read/write اغلب مورداستفاده قرار نمیگرند و میتوان آنها را به زمین متصل کرد. این کار ال سی دی را در بالاترین کنتراست و حالت خواندن قرار میدهد و ما فقط پایههای RS و ENABLE را برای فرستادن دیتا و کاراکترها کنترل میکنیم.
اتصالات LCD و Mega8 به ترتیب زیر است:
- پایه 1 یا VSS به زمین
- پایه 2 یا VDD یا VCC به 5 ولت
- پایه 3 یا VEE به زمین (حداکثر وضوح را بدست میدهد – بهترین حالت برای افراد مبتدی)
- پایه 4 یا RS (Register Selection) به PB0 میکروکنترلر
- پایه 5 یا RW (Read/Write) به زمین (ال سی دی را در حالت خواندن قرار میدهد و ارتباط را برای کاربر آسان میکند)
- پایه 6 یا E (ENABLE) به PB1 میکروکنترلر
- پایه 7 یا D0 به PD0 میکروکنترلر
- پایه 8 یا D1 به PD1 میکروکنترلر
- پایه 9 یا D2 به PD2 میکروکنترلر
- پایه 10 یا D3 به PD3 میکروکنترلر
- پایه 11 یا D4 به PD4 میکروکنترلر
- پایه 12 یا D5 به PD5 میکروکنترلر
- پایه 13 یا D6 به PD6 میکروکنترلر
- پایه 14 یا D7 به PD7 میکروکنترلر
مشاهده میکنید که ما از ارتباط 8 بیتی(D0-D7) استفاده کردهایم اما این کار ضرورتی ندارد و میتوان از ارتباط 4 بیتی نیز استفاده کرد (D4-D7) اما برنامه نویسی آن کمی پیچیده تر میشود.
بر اساس جدول بالا 10 پایه از ال سی دی به میکروکنترلر وصل میشود که 8 تای آنها برای دیتا و 2 تای دیگر برای کنترل میباشند.
شماتیک راه اندازی سنسور Flex با میکروکنترلر AVR:
ولتاژ دو سر R2 به طور کامل خطی نیست و دارای نویز است. برای فیلتر کردن نویز یک خازن موازی با هر یک از مقاومتهای مقسم ولتاژ قرار داده شده است.
در اینجا پتانسیومتر 1کیلو برای تنظیم دقت ADC استفاده شده است. اکنون به مبحث ADC میکرو Atmega8 میپردازیم.
در میکروکنترلر Mega8 ADC دارای رزولوشن 10 بیتی میباشد. بنابراین کنترلر میتواند حداقل تغییر Vref/2^10 را اندازهگیری کند و اگر Vref 5ولت باشد این مقدار برابر با 5 میلی ولت خواهد بود. با هر 5میلی ولت افزایش ولتاژ ورودی ADC یک واحد به خروجی دیجیتال افزوده میشود.
تنظیم رجیستر ADC میکروکنترلر AVR
اکنون باید براساس عبارات زیر رجیستر ADC را مقداردهی کنیم،
1.اول از همه باید قابلیت ADC را فعال کنیم.
2.در اینجا ما حداکثر ولتاژی که در ورودی داریم 5 ولت است بنابراین مرجع ولتاژ ADC را نیز 5 ولت تعیین میکنیم.
3.کنترلر قابلیتی دارد که تبدیل ADC را تنها در صورت وجود یک عامل تحریک خارجی انجام دهد، از آنجایی که ما به این قابلیت نیاز نداریم باید رجیسترهای ADC را طوری مقدار دهی کنیم که ADC در حالت پیوسته کار کند.
4.برای هر ADC فرکانس تبدیل (مقدار آنالوگ به دیجیتال) و دقت مقدار تبدیل شده خروجی با یکدیگر نسبت عکس دارند. بنابراین برای داشتن دقت بیشتر در خروجی باید فرکانس کمتری را انتخاب کنیم. برای حالت عادی کلاک ADC ضریب آن را روی حداکثر مقدار قرار میدهیم (2). از آنجایی که ما از کلاک داخلی 1Mhz استفاده میکنیم کلاک ADC (1000000/2) هرتز خواهد بود.
این 4 مورد تنها برای برای شروع کار با ADC کافی است.
تمامی 4 مورد بالا با دو رجیستر تنظیم میشوند.
قرمز (ADEN): این بیت برای فعال کردن ADC باید ست شود.
آبی (REFS1,REFS0): این دو بیت برای تنظیم مرجع ولتاژ استفاده میشوند (یا حداکثر ولتاژی که ما قرار است به ADC بدهیم )
چون ما میخواهیم ولتاژ مرجع 5 ولت باشد REFS0 باید ست شود، براساس جدول زیر:
زرد(ADFR): این بیت باید ست شود تا ADC به طور پیوسته کار کند.
صورتی (MUX0-MUX3): این 4 بیت برای تعیین کانال ورودی هستند. از آنجایی که ما از ADC0 یا PIN0 استفاده میکنیم طبق جدول زیر احتیاج به ست کردن هیچ بیتی نیست.
قهوهای(ADPS0-ADPS2): این 3 بیت برای تعیین ضریب کلاک ADC هستند. مطابق جدول برای ضریب 2 یک بیت باید ست شود.
سبز تیره(ADSC): این بیت برای شروع تبدیل ADC باید ست شود. مواقعی که میخواهیم تبدیل متوقف شود این بیت میتواند از درون برنامه غیرفعال شود.
ویدیو عملکرد مدار سنسور خمشی:
کد پروژه راه اندازی Flex Sensor:
#include <avr/io.h> //header to enable data flow control over pins #define F_CPU 1000000 //telling controller crystal frequency attached #include <util/delay.h> //header to enable delay function in program #define E 5 //giving name “enable” to 5th pin of PORTD, since it Is connected to LCD enable pin #define RS 6 //giving name “registerselection” to 6th pin of PORTD, since is connected to LCD RS pin void send_a_command(unsigned char command); void send_a_character(unsigned char character); void send_a_string(char *string_of_characters); int main(void) { DDRB = 0xFF; //putting portB and portD as output pins DDRD = 0xFF; _delay_ms(50);//giving delay of 50ms DDRC = 0;//Taking portC as input. ADMUX |=(1<<REFS0);//setting the reference of ADC ADCSRA |=(1<<ADEN)|(1<<ADFR)|(1<<ADPS0); //enabling the ADC, setting free running mode, setting prescalar 2 float i =0; float RESISTANCE= 0;//storing digital output char RESISTANCESHOW [7];//displaying digital output as resistance in 16*2 lcd send_a_command(0x01); //Clear Screen 0x01 = 00000001 _delay_ms(50); send_a_command(0x38);//telling lcd we are using 8bit command /data mode _delay_ms(50); send_a_command(0b00001111);//LCD SCREEN ON and courser blinking ADCSRA |=(1<<ADSC);//starting the ADC conversion send_a_string ("CIRCUIT DIGEST ");// displaying name send_a_command(0x80 + 0x40 + 0);// shifting cursor to 1st shell of second line send_a_string ("RESISTANCE=");// displaying name send_a_command(0x80 + 0x40 + 11);// shifting cursor to 10th shell of second line while(1) { i=ADC/204.8;//Now since it’s a 10bit ADC for every Vref(5V)/1024=5mV(4.88mV) we get one digital increment or for every 1V increment in input we get 204.8 count increment. So for finding voltage at ADC pin. dtostrf(RESISTANCE, 4, 1, RESISTANCESHOW); send_a_string(RESISTANCESHOW); send_a_string("K"); //dtostr(double precision value, width, precision, string that will store the numbers); // Value is either a direct value plugged into this place, or a variable to contains a value. //Width that is used with dtostrf is the number of characters in the number that includes the negative sign (-). For instance, if the number is -532.87, the width would be 7 including the negative sign and the decimal point. //Precision is how many numbers would be after the decimal point in the dtostrf usage. _delay_ms(50); send_a_command(0x80 + 0x40 + 11);//retuning to second line 10th shell. } } void send_a_command(unsigned char command) { PORTA = command; PORTD &= ~ (1<<RS); //putting 0 in RS to tell lcd we are sending command PORTD |= 1<<E; //telling lcd to receive command /data at the port _delay_ms(50); PORTD &= ~1<<E;//telling lcd we completed sending data PORTA= 0; } void send_a_character(unsigned char character) { PORTA= character; PORTD |= 1<<RS;//telling LCD we are sending data not commands PORTD |= 1<<E;//telling LCD to start receiving command/data _delay_ms(50); PORTD &= ~1<<E;//telling lcd we completed sending data/command PORTA = 0; } void send_a_string(char *string_of_characters) { while(*string_of_characters > 0) { send_a_character(*string_of_characters++); } }
منابع: